using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using NutriStat.Data;
using NutriStat.Statistics;
using AnthStat;
using MySql.Data.MySqlClient;
//using Excel = Microsoft.Office.Interop.Excel;

namespace NutriStat
{
    /// <summary>
    /// Main menu form
    /// </summary>
    public partial class FormMainMenu : NutriForm
    {
        #region Data
        #region Protected Data
        #endregion Protected Data

        #region Private Data
        private NutriPatient patient;
        private NutriConfig config;
        private NutriConfig oldConfig;
        private bool loadingRecord;          // Used to determine if we are navigating records or not
        private bool databaseLoaded;         // Used to determine if a database has been loaded yet
        private bool patientInfoChanged;     // Used to determine if basic patient data has been changed
        private bool resultsChanged;         // Used to determine if statistic results have changed
        private bool valueChanged;           // Used to determine if user-supplied value has changed        
        private Color uiGreen;
        private Color uiRed;
        private Color uiOrange;
        private Color uiYellow;
        private Color uiBlack;
        private Color uiWhite;
        #endregion Private Data

        #region Internal Data
        #endregion Internal Data        
        #endregion Data

        #region Constructors
        /// <summary>
        /// The constructor for the main menu form
        /// </summary>
        public FormMainMenu() : base()
        {
            InitializeComponent();            
            patient = new NutriPatient();
            LoadingRecord = false;            
            InputsUpdated = false;
            OutputsUpdated = false;
            PatientInfoChanged = false;
            DatabaseLoaded = false;
            dateTimePickerDOB.Checked = false;

            uiGreen = Color.FromArgb(133, 255, 133);
            uiRed = Color.FromArgb(255, 51, 51);
            uiOrange = Color.FromArgb(255, 192, 51);
            uiYellow = Color.FromArgb(255, 246, 0);
            uiBlack = Color.FromName("WindowText"); // can't use hard-coded black, otherwise we fail accessibility testing when high-contrast theme is used
            uiWhite = Color.FromName("Window"); // see above                        
        }
        #endregion Constructors

        #region Properties
        #region Public Properties
        /// <summary>
        /// Gets the patient object
        /// </summary>
        public NutriStat.NutriPatient Patient
        {
            get
            {
                return patient;
            }
        }

        /// <summary>
        /// Gets the form's configuration settings
        /// </summary>
        public NutriStat.NutriConfig Config
        {
            get
            {
                return config;
            }
        }  

        /// <summary>
        /// Gets/sets whether or not the user has changed a form control
        /// </summary>
        public bool InputsUpdated
        {
            get
            {
                return valueChanged;
            }
            set
            {
                valueChanged = value;
            }
        }

        /// <summary>
        /// Gets/sets whether or not NutriStat has changed statistic
        /// results
        /// </summary>
        public bool OutputsUpdated
        {
            get
            {
                return resultsChanged;
            }
            set
            {
                resultsChanged = value;
            }
        }

        /// <summary>
        /// Gets/sets whether or not the user has changed basic patient
        /// information (inclues only non-visit information such as date
        /// of birth, gender, name, mother, father, address).
        /// </summary>
        public bool PatientInfoChanged
        {
            get
            {
                return patientInfoChanged;
            }
            set
            {
                patientInfoChanged = value;
            }
        }

        /// <summary>
        /// Gets/sets whether or not a database has been loaded.
        /// </summary>
        public bool DatabaseLoaded
        {
            get
            {
                return databaseLoaded;
            }
            set
            {
                databaseLoaded = value;
            }
        }

        /// <summary>
        /// Gets/sets whether or not a record is currently being loaded
        /// </summary>
        public bool LoadingRecord
        {
            get
            {
                return loadingRecord;
            }
            set
            {
                loadingRecord = value;
            }
        }
        #endregion Public Properties

        #region Protected Properties
        #endregion Protected Properties

        #region Private Properties
        #endregion Private Properties
        #endregion Properties

        #region Methods
        #region Public Methods
        /// <summary>
        /// Gets precision level for z-scores from the configuration file.
        /// </summary>        
        /// <returns>int; represents level of decimal precision (2 = two decimal places, etc)</returns>
        internal int GetPrecisionZ()
        {
            return Config.PrecisionZ;
        }

        /// <summary>
        /// Gets precision level for percentiles from the configuration file.
        /// </summary>        
        /// <returns>int; represents level of decimal precision (2 = two decimal places, etc)</returns>
        internal int GetPrecisionC()
        {
            return Config.PrecisionC;            
        }

        /// <summary>
        /// Gets a format string based on the number of digits sent to the function.
        /// </summary>
        /// <param name="digits">Number of digits past the decimal point</param>
        /// <returns>string</returns>
        internal string GetPrecisionString(int digits)
        {
            #region Input Validation
            // Input validation
            if (digits < 0 || digits > 5)
            {
                throw new Exception(SharedStrings.ERROR_PARAMETER1 + digits.ToString());
            }
            #endregion

            string format = "{0:0.00}";  // default to two digits of precision

            switch (digits)
            {
                case 0:
                    format = "{0:0}";
                    break;
                case 1:
                    format = "{0:0.0}";
                    break;
                case 2:
                    format = "{0:0.00}";
                    break;
                case 3:
                    format = "{0:0.000}";
                    break;
                case 4:
                    format = "{0:0.0000}";
                    break;
                case 5:
                    format = "{0:0.00000}";
                    break;
                default:                
                    format = "{0:0.00}";
                    break;
            }

            return format;
        }   
        
        /// <summary>
        /// Refreshes all of the form's statistics and results.
        /// </summary>
        /// <param name="stats">The type of refresh to be conducted</param>
        internal override void RefreshData(int type)
        {
            // Depending on the number that gets passed in, we only refresh certain fields,
            // which saves us some compute power and improves efficiency. I did this because
            // doing a total refresh of all output boxes has a small but still noticeable
            // slowdown, and we want to avoid that if at all possible. 

            // 0 = Do everything
            // 1 = Age updated (will ential re-doing doing most measurements)
            // 2 = Sex updated (entails redoing all measurements)
            // 3 = Weight updated
            // 4 = Height updated
            // 5 = Head circumference updated  
            // 6 = MUAC updated
            // 7 = SSF updated
            // 8 = TSF updated

            // We simply run through our Calc functions which ensures all the output
            // form controls are updated. Note that noticable slowdowns occur the more of these
            // there are! Thus we try minimizing them as much as possible.

            // So instead of running through each one, we instead rig it so that only the 
            // appropriate calc functions are called for each control, e.g. changing the head
            // circumference measurement only calls CalcHeadCircum. This will improve speed.
            // The overlost lost from the IF statements should be more than made up for by
            // not redoing unecessary calcs...

            #region Input Validation
            // Input validation
            if (type < 0 || type > 8)
            {
                throw new Exception(SharedStrings.ERROR_PARAMETER1 + type.ToString());
            }
            #endregion

            double BMI = -1.0;

            if (!textBoxWeight.Text.Equals(NutriStringConstants.Empty) && !textBoxHeight.Text.Equals(NutriStringConstants.Empty) && type != 5 && type != 6)
            {
                double height = -1.0;
                height = Convert.ToDouble(textBoxHeight.Text);

                double weight = -1.0;
                weight = Convert.ToDouble(textBoxWeight.Text);

                if (textBoxWeightOz.Text != NutriStringConstants.Empty && textBoxWeightOz.Text != NutriStringConstants.Empty)
                {
                    weight = weight + (Convert.ToDouble(textBoxWeightOz.Text) / 16);
                }

                if (config.UnitsWeight.Equals(MeasurementUnits.Pound.Abbreviation))
                {
                    weight = weight * MeasurementUnits.Pound.ToKilograms();
                }

                if (config.UnitsHeight.Equals(MeasurementUnits.Inch.Abbreviation))
                {
                    height = height * MeasurementUnits.Inch.ToCentimeters();
                }

                height = height / 100;
                BMI = (weight) / (height * height);
                string BMIstr = BMI.ToString();
                Patient.Visit.BMI = BMIstr;
                textBoxBMI.Text = FormatZScore(BMIstr);
            }
            else if (string.IsNullOrEmpty(textBoxWeight.Text) && string.IsNullOrEmpty(textBoxHeight.Text))
            {
                Patient.Visit.BMI = NutriStringConstants.Null;
                textBoxBMI.Text = NutriStringConstants.Undefined;
            }

            Patient.Visit.Age = textBoxAgeMonths.Text;
            Patient.Visit.VisitDate = dateTimePickerDOM.Value;
            Patient.BirthDate = dateTimePickerDOB.Value;

            if (radioButtonFemale.Checked)
            {
                Patient.Gender = "F";
            }
            else
            {
                Patient.Gender = "M";
            }

            if (checkBoxRecumbent.Checked)
            {
                Patient.Visit.Recumbent = true;
            }
            else
            {
                Patient.Visit.Recumbent = false;
            }

            if (checkBoxEdema.Checked)
            {
                Patient.Visit.Edema = true;
            }
            else
            {
                Patient.Visit.Edema = false;
            }

            // Update Height
            if (!string.IsNullOrEmpty(textBoxHeight.Text) && (type == 4 || type == 0))
            {
                if (config.UnitsHeight.Equals(MeasurementUnits.Centimeter.Abbreviation))
                {
                    Patient.Visit.HeightMetric = textBoxHeight.Text;
                    Patient.Visit.HeightCustomary = (Convert.ToDouble(textBoxHeight.Text) * MeasurementUnits.Centimeter.ToInches()).ToString();
                }
                else
                {
                    Patient.Visit.HeightMetric = (Convert.ToDouble(textBoxHeight.Text) * MeasurementUnits.Inch.ToCentimeters()).ToString();
                    Patient.Visit.HeightCustomary = textBoxHeight.Text;                    
                }
            }            

            // Update Weight
            if (!string.IsNullOrEmpty(textBoxWeight.Text) && (type == 3 || type == 0))
            {
                if (config.UnitsWeight.Equals(MeasurementUnits.Kilogram.Abbreviation))
                {
                    Patient.Visit.WeightMetric = textBoxWeight.Text;
                    Patient.Visit.WeightCustomary = (Convert.ToDouble(textBoxWeight.Text) * MeasurementUnits.Kilogram.ToPounds()).ToString();
                }
                else
                {
                    Patient.Visit.WeightMetric = (Convert.ToDouble(textBoxWeight.Text) * MeasurementUnits.Pound.ToKilograms()).ToString();
                    Patient.Visit.WeightCustomary = textBoxWeight.Text;
                }
            }            

            // Update Head circumference
            if (!string.IsNullOrEmpty(textBoxHead.Text) && (type == 5 || type == 0))
            {
                if (config.UnitsHead.Equals(MeasurementUnits.Centimeter.Abbreviation))
                {
                    Patient.Visit.HeadCircumferenceMetric = textBoxHead.Text;
                    Patient.Visit.HeadCircumferenceCustomary = (Convert.ToDouble(textBoxHead.Text) * MeasurementUnits.Centimeter.ToInches()).ToString();
                }
                else
                {
                    Patient.Visit.HeadCircumferenceMetric = (Convert.ToDouble(textBoxHead.Text) * MeasurementUnits.Inch.ToCentimeters()).ToString();
                    Patient.Visit.HeadCircumferenceCustomary = textBoxHead.Text;
                }
            }            

            // MUAC updated
            if (!string.IsNullOrEmpty(textBoxMUAC.Text) && (type == 6 || type == 0))
            {
                if (config.UnitsArm.Equals(MeasurementUnits.Centimeter.Abbreviation))
                {
                    Patient.Visit.ArmCircumferenceMetric = textBoxMUAC.Text;
                    Patient.Visit.ArmCircumferenceCustomary = (Convert.ToDouble(textBoxMUAC.Text) * MeasurementUnits.Centimeter.ToInches()).ToString();
                }
                else
                {
                    Patient.Visit.ArmCircumferenceMetric = (Convert.ToDouble(textBoxMUAC.Text) * MeasurementUnits.Inch.ToCentimeters()).ToString();
                    Patient.Visit.ArmCircumferenceCustomary = textBoxMUAC.Text;
                }
            }            

            // Subscapular skin fold
            if (!string.IsNullOrEmpty(textBoxSSF.Text) && (type == 7 || type == 0))
            {
                if (config.UnitsSkin.Equals(MeasurementUnits.Millimeter.Abbreviation))
                {
                    Patient.Visit.SubscapularSkinFoldMetric = textBoxSSF.Text;
                    Patient.Visit.SubscapularSkinFoldCustomary = (Convert.ToDouble(textBoxSSF.Text) * MeasurementUnits.Millimeter.ToInches()).ToString();
                }
                else
                {
                    Patient.Visit.SubscapularSkinFoldMetric = (Convert.ToDouble(textBoxSSF.Text) * MeasurementUnits.Inch.ToMillimeters()).ToString();
                    Patient.Visit.SubscapularSkinFoldCustomary = textBoxSSF.Text;
                }
            }            

            // Triceps skin fold
            if (!string.IsNullOrEmpty(textBoxTSF.Text) && (type == 8 || type == 0))
            {
                if (config.UnitsSkin.Equals(MeasurementUnits.Millimeter.Abbreviation))
                {
                    Patient.Visit.TricepsSkinFoldMetric = textBoxTSF.Text;
                    Patient.Visit.TricepsSkinFoldCustomary = (Convert.ToDouble(textBoxTSF.Text) * MeasurementUnits.Millimeter.ToInches()).ToString();
                }
                else
                {
                    Patient.Visit.TricepsSkinFoldMetric = (Convert.ToDouble(textBoxTSF.Text) * MeasurementUnits.Inch.ToMillimeters()).ToString();
                    Patient.Visit.TricepsSkinFoldCustomary = textBoxTSF.Text;
                }
            }            
            Patient.Visit.Gender = Patient.Gender;
            Patient.Visit.GenerateStatistics(type);

            if (config.ReferenceType.Equals(GrowthReferenceTypes.CDC2000))
            {
                textBoxHeadCircumZ.Text = FormatZScore(Patient.Visit.CDCHCircumZ);
                textBoxHTforAgeZ.Text = FormatZScore(Patient.Visit.CDCHAZ);
                textBoxWTforAgeZ.Text = FormatZScore(Patient.Visit.CDCWAZ);
                textBoxWTforHTZ.Text = FormatZScore(Patient.Visit.CDCWHZ);
                textBoxBMIZ.Text = FormatZScore(Patient.Visit.CDCBMIZ);
                textBoxSSFZ.Text = NutriStringConstants.Undefined;
                textBoxTSFZ.Text = NutriStringConstants.Undefined;
                textBoxMUACZ.Text = NutriStringConstants.Undefined;
                textBoxHeadCircumP.Text = FormatPercentile(Patient.Visit.CDCHCircumC);
                textBoxHTforAgeP.Text = FormatPercentile(Patient.Visit.CDCHAC);
                textBoxWTforAgeP.Text = FormatPercentile(Patient.Visit.CDCWAC);
                textBoxWTforHTP.Text = FormatPercentile(Patient.Visit.CDCWHC);
                textBoxBMIPercentile.Text = FormatPercentile(Patient.Visit.CDCBMIC);
                textBoxSSFP.Text = NutriStringConstants.Undefined;
                textBoxTSFP.Text = NutriStringConstants.Undefined;
                textBoxMUACP.Text = NutriStringConstants.Undefined;
                textBoxHTforAgeF.Text = CDC2000GrowthReference.CheckHeightAgeFlagged(Patient.Visit.CDCHAFlag);
                textBoxWTforAgeF.Text = CDC2000GrowthReference.CheckWeightAgeFlagged(Patient.Visit.CDCWAFlag);
                textBoxWTforHTF.Text = CDC2000GrowthReference.CheckWeightHeightFlagged(Patient.Visit.CDCWHFlag);
                textBoxBMIF.Text = CDC2000GrowthReference.CheckBMIFlagged(Patient.Visit.CDCBMIFlag);
            }
            if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO2007))
            {
                textBoxHeadCircumZ.Text = NutriStringConstants.Undefined;
                textBoxHTforAgeZ.Text = FormatZScore(Patient.Visit.WHO2007HAZ);
                textBoxWTforAgeZ.Text = FormatZScore(Patient.Visit.WHO2007WAZ);
                textBoxWTforHTZ.Text = NutriStringConstants.Undefined;
                textBoxBMIZ.Text = FormatZScore(Patient.Visit.WHO2007BMIZ);
                textBoxSSFZ.Text = NutriStringConstants.Undefined;
                textBoxTSFZ.Text = NutriStringConstants.Undefined;
                textBoxMUACZ.Text = NutriStringConstants.Undefined;
                textBoxHeadCircumP.Text = NutriStringConstants.Undefined;
                textBoxHTforAgeP.Text = FormatPercentile(Patient.Visit.WHO2007HAC);
                textBoxWTforAgeP.Text = FormatPercentile(Patient.Visit.WHO2007WAC);
                textBoxWTforHTP.Text = NutriStringConstants.Undefined;
                textBoxBMIPercentile.Text = FormatPercentile(Patient.Visit.WHO2007BMIC);
                textBoxSSFP.Text = NutriStringConstants.Undefined;
                textBoxTSFP.Text = NutriStringConstants.Undefined;
                textBoxMUACP.Text = NutriStringConstants.Undefined;
                textBoxHTforAgeF.Text = WHO2007GrowthReference.CheckHeightAgeFlagged(Patient.Visit.WHO2007HAFlag);
                textBoxWTforAgeF.Text = WHO2007GrowthReference.CheckWeightAgeFlagged(Patient.Visit.WHO2007WAFlag);
                textBoxWTforHTF.Text = NutriStringConstants.Empty;
                textBoxBMIF.Text = WHO2007GrowthReference.CheckBMIFlagged(Patient.Visit.WHO2007BMIFlag);
            }
            else if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO2006))
            {
                textBoxHeadCircumZ.Text = FormatZScore(Patient.Visit.WHO2006HCircumZ);
                textBoxHTforAgeZ.Text = FormatZScore(Patient.Visit.WHO2006HAZ);
                textBoxWTforAgeZ.Text = FormatZScore(Patient.Visit.WHO2006WAZ);
                textBoxWTforHTZ.Text = FormatZScore(Patient.Visit.WHO2006WHZ);
                textBoxBMIZ.Text = FormatZScore(Patient.Visit.WHO2006BMIZ);
                textBoxSSFZ.Text = FormatZScore(Patient.Visit.WHO2006SSFZ);
                textBoxTSFZ.Text = FormatZScore(Patient.Visit.WHO2006TSFZ);
                textBoxMUACZ.Text = FormatZScore(Patient.Visit.WHO2006MUACZ);
                textBoxHeadCircumP.Text = FormatPercentile(Patient.Visit.WHO2006HCircumC);
                textBoxHTforAgeP.Text = FormatPercentile(Patient.Visit.WHO2006HAC);
                textBoxWTforAgeP.Text = FormatPercentile(Patient.Visit.WHO2006WAC);
                textBoxWTforHTP.Text = FormatPercentile(Patient.Visit.WHO2006WHC);
                textBoxBMIPercentile.Text = FormatPercentile(Patient.Visit.WHO2006BMIC);
                textBoxSSFP.Text = FormatPercentile(Patient.Visit.WHO2006SSFC);
                textBoxTSFP.Text = FormatPercentile(Patient.Visit.WHO2006TSFC);
                textBoxMUACP.Text = FormatPercentile(Patient.Visit.WHO2006MUACC);
                textBoxHTforAgeF.Text = WHO2006GrowthReference.CheckHeightAgeFlagged(Patient.Visit.WHO2006HAFlag);
                textBoxWTforAgeF.Text = WHO2006GrowthReference.CheckWeightAgeFlagged(Patient.Visit.WHO2006WAFlag);
                textBoxWTforHTF.Text = WHO2006GrowthReference.CheckWeightAgeFlagged(Patient.Visit.WHO2006WHFlag);
                textBoxBMIF.Text = WHO2006GrowthReference.CheckBMIFlagged(Patient.Visit.WHO2006BMIFlag);
                textBoxHeadCircumF.Text = WHO2006GrowthReference.CheckHeadFlagged(Patient.Visit.WHO2006HeadFlag);
                textBoxMUACF.Text = WHO2006GrowthReference.CheckMUACAgeFlagged(Patient.Visit.WHO2006MUACFlag);
                textBoxSSFF.Text = WHO2006GrowthReference.CheckSSFAgeFlagged(Patient.Visit.WHO2006SSFFlag);
                textBoxTSFF.Text = WHO2006GrowthReference.CheckTSFAgeFlagged(Patient.Visit.WHO2006TSFFlag);
            }
            else if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO1978))
            {
                textBoxHeadCircumZ.Text = NutriStringConstants.Undefined;
                textBoxHTforAgeZ.Text = FormatZScore(Patient.Visit.WHO1978HAZ);
                textBoxWTforAgeZ.Text = FormatZScore(Patient.Visit.WHO1978WAZ);
                textBoxWTforHTZ.Text = FormatZScore(Patient.Visit.WHO1978WHZ);
                textBoxBMIZ.Text = NutriStringConstants.Undefined;
                textBoxSSFZ.Text = NutriStringConstants.Undefined;
                textBoxTSFZ.Text = NutriStringConstants.Undefined;
                textBoxMUACZ.Text = NutriStringConstants.Undefined;
                textBoxHeadCircumP.Text = NutriStringConstants.Undefined;
                textBoxHTforAgeP.Text = FormatPercentile(Patient.Visit.WHO1978HAC);
                textBoxWTforAgeP.Text = FormatPercentile(Patient.Visit.WHO1978WAC);
                textBoxWTforHTP.Text = FormatPercentile(Patient.Visit.WHO1978WHC);
                textBoxBMIPercentile.Text = NutriStringConstants.Undefined;
                textBoxSSFP.Text = NutriStringConstants.Undefined;
                textBoxTSFP.Text = NutriStringConstants.Undefined;
                textBoxMUACP.Text = NutriStringConstants.Undefined;
            }

            if (config.ResultsLegacyArm)
            {
                textBoxMUACAge.Text = FormatZScore(Patient.Visit.MUACAgeZ);
                textBoxMUACHeight.Text = FormatZScore(Patient.Visit.MUACHeightZ);
            }

            UpdateFlags();            

        } // end RefreshData()        
        
        /// <summary>
        /// Opens a database and data table for viewing and updating.
        /// </summary>
        protected internal override void OpenDatabase()
        {
            if (Patient.OpenDatabase() == false)
            {
                return;
            }

            this.Text = SharedStrings.NUTRISTAT + " " + SharedStrings.DASH + " " + Patient.Table.TableName;
            
            buttonLeft.Enabled = true;
            buttonRight.Enabled = true;
            buttonDOMLeft.Enabled = true;
            buttonDOMRight.Enabled = true;
            buttonNew.Enabled = true;
            buttonDOMNew.Enabled = true;
            buttonRightLast.Enabled = true;
            buttonLeftFirst.Enabled = true;
            PopulateFormControls();
            DatabaseLoaded = true;

            UpdateStatusBar();
            UpdateGridView();

            config.AddDataTable(Patient.ConnectionString + "::" + Patient.Table.TableName);
            config.LoadConfigFile();
            LoadConfigFile(config);
            
        } // end OpenDatabase()


        /// <summary>
        /// Converts all user-supplied input 
        /// </summary>
        protected internal void ConvertMeasurements()
        {
            try
            {
                // Arm units changed
                if (this.config.UnitsArm.Equals(MeasurementUnits.Centimeter.Abbreviation) && (this.oldConfig.UnitsArm.Equals(MeasurementUnits.Inch.Abbreviation)))
                {
                    double measurement = Convert.ToDouble(textBoxMUAC.Text);
                    textBoxMUAC.Text = (measurement * MeasurementUnits.Inch.ToCentimeters()).ToString();
                }
                if (this.config.UnitsArm.Equals(MeasurementUnits.Inch.Abbreviation) && (this.oldConfig.UnitsArm.Equals(MeasurementUnits.Centimeter.Abbreviation)))
                {
                    double measurement = Convert.ToDouble(textBoxMUAC.Text);
                    textBoxMUAC.Text = (measurement * MeasurementUnits.Centimeter.ToInches()).ToString();
                }
            }
            catch 
            { 
            }

            try
            {
                // Head units changed
                if (this.config.UnitsHead.Equals(MeasurementUnits.Centimeter.Abbreviation) && (this.oldConfig.UnitsHead.Equals(MeasurementUnits.Inch.Abbreviation)))
                {
                    double measurement = Convert.ToDouble(textBoxHead.Text);
                    textBoxHead.Text = (measurement * MeasurementUnits.Inch.ToCentimeters()).ToString();
                }
                if (this.config.UnitsHead.Equals(MeasurementUnits.Inch.Abbreviation) && (this.oldConfig.UnitsHead.Equals(MeasurementUnits.Centimeter.Abbreviation)))
                {
                    double measurement = Convert.ToDouble(textBoxHead.Text);
                    textBoxHead.Text = (measurement * MeasurementUnits.Centimeter.ToInches()).ToString();
                }
            }
            catch
            {
            }

            try
            {
                // Height units changed
                if (this.config.UnitsHeight.Equals(MeasurementUnits.Centimeter.Abbreviation) && (this.oldConfig.UnitsHeight.Equals(MeasurementUnits.Inch.Abbreviation)))
                {
                    double measurement = Convert.ToDouble(textBoxHeight.Text);
                    textBoxHeight.Text = (measurement * MeasurementUnits.Inch.ToCentimeters()).ToString();
                }
                if (this.config.UnitsHeight.Equals(MeasurementUnits.Inch.Abbreviation) && (this.oldConfig.UnitsHeight.Equals(MeasurementUnits.Centimeter.Abbreviation)))
                {
                    double measurement = Convert.ToDouble(textBoxHeight.Text);
                    textBoxHeight.Text = (measurement * MeasurementUnits.Centimeter.ToInches()).ToString();
                }
            }
            catch
            {
            }

            try
            {
                // TSF/SSF units changed
                if (this.config.UnitsSkin.Equals(MeasurementUnits.Millimeter.Abbreviation) && (this.oldConfig.UnitsSkin.Equals(MeasurementUnits.Inch.Abbreviation)))
                {
                    double measurement = Convert.ToDouble(textBoxSSF.Text);
                    textBoxSSF.Text = (measurement * MeasurementUnits.Inch.ToMillimeters()).ToString();
                    measurement = Convert.ToDouble(textBoxTSF.Text);
                    textBoxTSF.Text = (measurement * MeasurementUnits.Inch.ToMillimeters()).ToString();
                }
                if (this.config.UnitsSkin.Equals(MeasurementUnits.Inch.Abbreviation) && (this.oldConfig.UnitsSkin.Equals(MeasurementUnits.Millimeter.Abbreviation)))
                {
                    double measurement = Convert.ToDouble(textBoxSSF.Text);
                    textBoxSSF.Text = (measurement * MeasurementUnits.Millimeter.ToInches()).ToString();
                    measurement = Convert.ToDouble(textBoxTSF.Text);
                    textBoxTSF.Text = (measurement * MeasurementUnits.Inch.ToMillimeters()).ToString();
                }
            }
            catch
            {
            }

            try
            {
                // Weight units changed
                if (this.config.UnitsWeight.Equals(MeasurementUnits.Kilogram.Abbreviation) && (this.oldConfig.UnitsWeight.Equals(MeasurementUnits.Pound.Abbreviation)))
                {
                    double weight = Convert.ToDouble(textBoxWeight.Text);
                    if (textBoxWeightOz.Text.Length > 0)
                    {
                        weight = weight + Convert.ToDouble(textBoxWeightOz.Text);
                    }
                    textBoxWeight.Text = (weight * MeasurementUnits.Pound.ToKilograms()).ToString();
                }
                if (this.config.UnitsWeight.Equals(MeasurementUnits.Pound.Abbreviation) && (this.oldConfig.UnitsWeight.Equals(MeasurementUnits.Kilogram.Abbreviation)))
                {
                    double weight = Convert.ToDouble(textBoxWeight.Text);
                    textBoxWeight.Text = (weight * MeasurementUnits.Kilogram.ToPounds()).ToString();
                }
            }
            catch
            {
            }


        } // ConvertMeasurements
        
        /// <summary>
        /// Configures the form controls based on the user's preferences, as defined in the options.
        /// </summary>
        protected internal override void ConfigureFormControls()
        {
            if(!DatabaseLoaded) 
            {
                buttonLeft.Enabled = false;
                buttonRight.Enabled = false;
                buttonDOMLeft.Enabled = false;
                buttonDOMRight.Enabled = false;
                buttonNew.Enabled = false;
                buttonDOMNew.Enabled = false;
                buttonRightLast.Enabled = false;
                buttonLeftFirst.Enabled = false;
            }

            if (config.DeleteButton)
            {
                buttonDelete.Enabled = true;
            }
            else
            {
                buttonDelete.Enabled = false;
            }

            if (config.SurveyFields)
            {
                integerTextBoxCluster.Visible = true;
                integerTextBoxTeam.Visible = true;
                integerTextBoxHousehold.Visible = true;
                labelCluster.Visible = true;
                labelTeam.Visible = true;
                labelHousehold.Visible = true;
            }
            else
            {
                integerTextBoxCluster.Visible = false;
                integerTextBoxTeam.Visible = false;
                integerTextBoxHousehold.Visible = false;
                labelCluster.Visible = false;
                labelTeam.Visible = false;
                labelHousehold.Visible = false;
            }

            recentlyOpenedFilesToolStripMenuItem.DropDownItems.Clear();
            for (int i = 0; i < config.recentFiles.Count; i++)
            {
                recentlyOpenedFilesToolStripMenuItem.DropDownItems.Add(config.recentFiles[i]);
                recentlyOpenedFilesToolStripMenuItem.DropDownItems[i].Click += new System.EventHandler(this.MRU_Click);
            }

            labelAge.Text = SharedStrings.AGE;
            labelBMI.Text = SharedStrings.BODY_MASS_INDEX_ABBR;
            labelDOB.Text = SharedStrings.DATE_OF_BIRTH;
            labelFirstName.Text = SharedStrings.FIRST_NAME;
            labelFlag.Text = SharedStrings.FLAG;
            labelHead.Text = SharedStrings.HEAD_CIRCUMFERENCE;
            labelHeadCircum.Text = SharedStrings.HEAD_CIRCUMFERENCE_FOR_AGE;
            labelHeight.Text = SharedStrings.HEIGHT;
            labelHTforAge.Text = SharedStrings.HEIGHT_FOR_AGE;
            labelIDNumber.Text = SharedStrings.ID_NUMBER;
            labelLastName.Text = SharedStrings.LAST_NAME;            
            labelMUAC.Text = SharedStrings.MID_UPPER_ARM_CIRCUMFERENCE_ABBR1;
            labelMUACAge.Text = SharedStrings.Z_FOR_AGE;
            labelMUACHeight.Text = SharedStrings.Z_FOR_HEIGHT;
            labelMUACLegacy.Text = SharedStrings.MID_UPPER_ARM_CIRCUMFERENCE_ABBR2;
            labelMUACZ.Text = SharedStrings.MID_UPPER_ARM_CIRCUMFERENCE_ABBR2;
            labelNotes.Text = SharedStrings.NOTES;            
            labelPercentile.Text = SharedStrings.PERCENTILE;
            labelRef1.Text = SharedStrings.REFERENCE_1;
            labelRef2.Text = SharedStrings.REFERENCE_2;
            labelSex.Text = SharedStrings.SEX;
            labelSSF.Text = SharedStrings.SUBSCAPULAR_SKIN_FOLD;
            labelSSFResults.Text = SharedStrings.SUBSCAPULAR_SKIN_FOLD_FOR_AGE;
            labelTSF.Text = SharedStrings.TRICEPS_SKIN_FOLD;
            labelTSFResults.Text = SharedStrings.TRICEPS_SKIN_FOLD_FOR_AGE;
            labelWeight.Text = SharedStrings.WEIGHT;
            labelWHOFlag.Text = SharedStrings.FLAG;
            labelWTforAge.Text = SharedStrings.WEIGHT_FOR_AGE;
            labelWTforHT.Text = SharedStrings.WEIGHT_FOR_HEIGHT;
            labelZScore.Text = SharedStrings.Z_SCORE;
            
            checkBoxEdema.Text = SharedStrings.EDEMA;
            checkBoxRecumbent.Text = SharedStrings.RECUMBENT;

            buttonDelete.Text = SharedStrings.DELETE;
            buttonGraph.Text = SharedStrings.GRAPH;
            buttonGrid.Text = SharedStrings.GRID;
            buttonSearch.Text = SharedStrings.FIND;
            buttonDOMNew.Text = SharedStrings.NEW;
            buttonNew.Text = SharedStrings.NEW;

            fileToolStripMenuItem.Text = SharedStrings.MENU_FILE;
            editToolStripMenuItem.Text = SharedStrings.MENU_EDIT;
            viewToolStripMenuItem.Text = SharedStrings.MENU_VIEW;
            toolsToolStripMenuItem.Text = SharedStrings.MENU_TOOLS;
            helpToolStripMenuItem.Text = SharedStrings.MENU_HELP;

            saveRecordToolStripMenuItem.Text = SharedStrings.MENU_FILE_SAVE_RECORD;
            printPreviewToolStripMenuItem.Text = SharedStrings.MENU_FILE_PRINT_PREVIEW;
            printToolStripMenuItem.Text = SharedStrings.MENU_FILE_PRINT;
            newTableToolStripMenuItem.Text = SharedStrings.MENU_FILE_NEW_TABLE;
            openTableToolStripMenuItem.Text = SharedStrings.MENU_FILE_OPEN_TABLE;
            exportToolStripMenuItem.Text = SharedStrings.MENU_FILE_EXPORT;
            externalDataToolStripMenuItem.Text = SharedStrings.MENU_FILE_EXTERNAL_DATA;
            exitToolStripMenuItem.Text = SharedStrings.MENU_FILE_EXIT;
            addStatisticsToolStripMenuItem.Text = SharedStrings.MENU_FILE_ADD_STATISTICS;
            importToolStripMenuItem.Text = SharedStrings.MENU_FILE_IMPORT;

            allRecordsForCurrentIDToolStripMenuItem.Text = SharedStrings.MENU_FILE_EXPORT_THIS;
            allRecordsToolStripMenuItem.Text = SharedStrings.MENU_FILE_EXPORT_ALL;
            customToolStripMenuItem.Text = SharedStrings.MENU_FILE_EXPORT_CUSTOM;

            cutToolStripMenuItem.Text = SharedStrings.MENU_EDIT_CUT;
            copyToolStripMenuItem.Text = SharedStrings.MENU_EDIT_COPY;
            pasteToolStripMenuItem.Text = SharedStrings.MENU_EDIT_PASTE;
            findToolStripMenuItem.Text = SharedStrings.MENU_EDIT_FIND;

            generateReportToolStripMenuItem.Text = SharedStrings.MENU_TOOLS_GENERATE_REPORT;
            optionsToolStripMenuItem.Text = SharedStrings.MENU_TOOLS_OPTIONS;
            graphToolStripMenuItem.Text = SharedStrings.MENU_TOOLS_GRAPH;

            gridToolStripMenuItem.Text = SharedStrings.MENU_VIEW_GRID;
            refreshToolStripMenuItem.Text = SharedStrings.MENU_VIEW_REFRESH;

            aboutToolStripMenuItem.Text = SharedStrings.MENU_HELP_ABOUT;
            contentsToolStripMenuItem.Text = SharedStrings.MENU_HELP_CONTENTS;

            groupBoxResults.Text = string.Format(SharedStrings.RESULTS_HEADING, SharedStrings.RESULTS, SharedStrings.DASH, config.ReferenceType);                          

            tsslLanguage.Text = config.CultureCode;            

            textBoxHTforAgeP.Visible = false;
            textBoxBMIPercentile.Visible = false;
            textBoxMUACP.Visible = false;
            textBoxWTforAgeP.Visible = false;
            textBoxWTforHTP.Visible = false;
            textBoxSSFP.Visible = false;
            textBoxTSFP.Visible = false;
            textBoxHeadCircumP.Visible = false;
            textBoxHTforAgeZ.Visible = false;
            textBoxBMIZ.Visible = false;
            textBoxMUACZ.Visible = false;
            textBoxWTforAgeZ.Visible = false;
            textBoxWTforHTZ.Visible = false;
            textBoxSSFZ.Visible = false;
            textBoxTSFZ.Visible = false;
            textBoxHeadCircumZ.Visible = false;

            if (config.Name)
            {
                textBoxFirstName.Visible = true;
                textBoxLastName.Visible = true;
                labelFirstName.Visible = true;
                labelLastName.Visible = true;
            }
            else
            {
                textBoxFirstName.Visible = false;
                textBoxLastName.Visible = false;
                labelFirstName.Visible = false;
                labelLastName.Visible = false;                
            }

            if (config.Birthdate)
            {
                dateTimePickerDOB.Visible = true;
                labelDOB.Visible = true;
            }
            else
            {
                dateTimePickerDOB.Visible = false;
                labelDOB.Visible = false;
            }

            if (config.Notes)
            {
                labelNotes.Visible = true;
                textBoxNotes.Visible = true;
            }
            else
            {
                labelNotes.Visible = false;
                textBoxNotes.Visible = false;
            }

            if (config.Age)
            {
                textBoxAgeMonths.Visible = true;
                textBoxAgeYears.Visible = true;
                labelAge.Visible = true;
                labelYears.Visible = true;
                labelMonths.Visible = true;
            }
            else
            {
                textBoxAgeMonths.Visible = false;
                textBoxAgeYears.Visible = false;
                labelAge.Visible = false;
                labelYears.Visible = false;
                labelMonths.Visible = false;
            }

            if (config.Height)
            {
                textBoxHeight.Visible = true;
                labelHeight.Visible = true;
                labelUnitsHeight.Visible = true;
            }
            else
            {
                textBoxHeight.Visible = false;
                labelHeight.Visible = false;
                labelUnitsHeight.Visible = false;
            }

            if (config.Weight)
            {
                textBoxWeight.Visible = true;
                textBoxWeightOz.Visible = true;
                labelWeight.Visible = true;
            }
            else
            {
                textBoxWeight.Visible = false;
                textBoxWeightOz.Visible = false;
                labelWeight.Visible = false;
            }

            if (config.Edema)
            {
                checkBoxEdema.Visible = true;
            }
            else
            {
                checkBoxEdema.Visible = false;                
            }

            if (config.HeadCircumference)
            {
                textBoxHead.Visible = true;
                labelHead.Visible = true;
                labelUnitsHead.Visible = true;
            }
            else
            {
                textBoxHead.Visible = false;
                labelHead.Visible = false;
                labelUnitsHead.Visible = false;
            }

            if (config.ArmCircumference)
            {
                textBoxMUAC.Visible = true;
                labelMUAC.Visible = true;
                labelUnitsArm.Visible = true;
            }
            else
            {
                textBoxMUAC.Visible = false;
                labelMUAC.Visible = false;
                labelUnitsArm.Visible = false;
            }

            if (config.SubscapularSkinFold)
            {
                textBoxSSF.Visible = true;
                labelSSF.Visible = true;
                labelUnitsTSF.Visible = true;
            }
            else
            {
                textBoxSSF.Visible = false;
                labelSSF.Visible = false;
                labelUnitsTSF.Visible = false;
            }

            if (config.TricepsSkinFold)
            {
                textBoxTSF.Visible = true;
                labelTSF.Visible = true;
                labelUnitsSSF.Visible = true;
            }
            else
            {
                textBoxTSF.Visible = false;                
                labelTSF.Visible = false;
                labelUnitsSSF.Visible = false;
            }
            
            // RESULTS
            if (config.ResultsArm)
            {
                textBoxMUACZ.Visible = true;
                textBoxMUACP.Visible = true;                
                labelMUACZ.Visible = true;
                pictureBoxGraphMUACA.Visible = true;
            }
            else
            {
                textBoxMUACZ.Visible = false;
                textBoxMUACP.Visible = false;
                textBoxMUACF.Visible = false;
                labelMUACZ.Visible = false;
                pictureBoxGraphMUACA.Visible = false;
            }

            if (config.ResultsLegacyArm)
            {
                textBoxMUACAge.Visible = true;
                textBoxMUACHeight.Visible = true;
                labelSup1.Visible = true;
                labelSup2.Visible = true;
                labelSup3.Visible = true;
                labelSup4.Visible = true;
                labelRef1.Visible = true;
                labelRef2.Visible = true;
                labelMUACAge.Visible = true;
                labelMUACHeight.Visible = true;
                labelMUACLegacy.Visible = true;
            }
            else
            {
                textBoxMUACAge.Visible = false;
                textBoxMUACHeight.Visible = false;
                labelSup1.Visible = false;
                labelSup2.Visible = false;
                labelSup3.Visible = false;
                labelSup4.Visible = false;
                labelRef1.Visible = false;
                labelRef2.Visible = false;
                labelMUACAge.Visible = false;
                labelMUACHeight.Visible = false;
                labelMUACLegacy.Visible = false;
            }

            if (config.ResultsBMI)
            {
                textBoxBMIPercentile.Visible = true;
                textBoxBMIZ.Visible = true;
                textBoxBMI.Visible = true;
                labelBMI.Visible = true;
                pictureBoxGraphBMI.Visible = true;
            }
            else
            {
                textBoxBMIPercentile.Visible = false;
                textBoxBMIZ.Visible = false;
                textBoxBMI.Visible = false;
                textBoxBMIF.Visible = false;
                labelBMI.Visible = false;
                pictureBoxGraphBMI.Visible = false;
            }

            if (config.ResultsHA)
            {
                textBoxHTforAgeP.Visible = true;
                textBoxHTforAgeZ.Visible = true;
                labelHTforAge.Visible = true;
                pictureBoxGraphHA.Visible = true;
            }
            else
            {
                textBoxHTforAgeP.Visible = false;
                textBoxHTforAgeZ.Visible = false;
                textBoxHTforAgeF.Visible = false;
                labelHTforAge.Visible = false;
                pictureBoxGraphHA.Visible = false;
            }

            if (config.ResultsWA)
            {
                textBoxWTforAgeP.Visible = true;
                textBoxWTforAgeZ.Visible = true;
                labelWTforAge.Visible = true;
                pictureBoxGraphWA.Visible = true;
            }
            else
            {
                textBoxWTforAgeP.Visible = false;
                textBoxWTforAgeZ.Visible = false;
                textBoxWTforAgeF.Visible = false;
                labelWTforAge.Visible = false;
                pictureBoxGraphHA.Visible = false;
            }

            if (config.ResultsWH)
            {
                textBoxWTforHTP.Visible = true;
                textBoxWTforHTZ.Visible = true;
                labelWTforHT.Visible = true;
                pictureBoxGraphWH.Visible = true;
            }
            else
            {
                textBoxWTforHTP.Visible = false;
                textBoxWTforHTZ.Visible = false;
                textBoxWTforHTF.Visible = false;
                labelWTforHT.Visible = false;
                pictureBoxGraphWH.Visible = false;
            }

            // Head circumference
            if (config.ResultsHead)
            {
                textBoxHeadCircumP.Visible = true;
                textBoxHeadCircumZ.Visible = true;
                labelHeadCircum.Visible = true;
                pictureBoxGraphHCA.Visible = true;
            }
            else
            {
                textBoxHeadCircumP.Visible = false;
                textBoxHeadCircumZ.Visible = false;
                textBoxHeadCircumF.Visible = false;
                labelHeadCircum.Visible = false;
                pictureBoxGraphHCA.Visible = false;
            }

            // Skin folds
            if (config.ResultsSSF)
            {
                textBoxSSFP.Visible = true;
                textBoxSSFZ.Visible = true;
                labelSSFResults.Visible = true;
            }
            else
            {
                textBoxSSFP.Visible = false;
                textBoxSSFZ.Visible = false;
                textBoxSSFF.Visible = false;
                labelSSFResults.Visible = false;
            }
            
            if (config.ResultsTSF)
            {
                textBoxTSFP.Visible = true;
                textBoxTSFZ.Visible = true;
                labelTSFResults.Visible = true;
            }
            else
            {
                textBoxTSFP.Visible = false;
                textBoxTSFZ.Visible = false;
                textBoxTSFF.Visible = false;
                labelTSFResults.Visible = false;
            }

            // Do flags
            if (config.ResultsFlag)
            {
                if (config.ReferenceType.Equals(GrowthReferenceTypes.CDC2000) || config.ReferenceType.Equals(GrowthReferenceTypes.WHO2007))
                {
                    if (config.ResultsHA)
                    {
                        textBoxHTforAgeF.Visible = true;
                    }

                    if (config.ResultsBMI)
                    {
                        textBoxBMIF.Visible = true;
                    }

                    if (config.ResultsWA)
                    {
                        textBoxWTforAgeF.Visible = true;
                    }

                    if (config.ResultsWH && !config.ReferenceType.Equals(GrowthReferenceTypes.WHO2007))
                    {
                        textBoxWTforHTF.Visible = true;
                    }
                    else
                    {
                        textBoxWTforHTF.Visible = false;
                    }

                    textBoxWHOFlag.Visible = false;
                    labelWHOFlag.Visible = false;
                    textBoxHeadCircumF.Visible = false;
                    textBoxMUACF.Visible = false;
                    textBoxSSFF.Visible = false;
                    textBoxTSFF.Visible = false;
                }
                if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO2006))
                {
                    if (config.ResultsHA)
                    {
                        textBoxHTforAgeF.Visible = true;
                    }

                    if (config.ResultsBMI)
                    {
                        textBoxBMIF.Visible = true;
                    }

                    if (config.ResultsWA)
                    {
                        textBoxWTforAgeF.Visible = true;
                    }

                    if (config.ResultsWH)
                    {
                        textBoxWTforHTF.Visible = true;
                    }

                    if (config.ResultsArm)
                    {
                        textBoxMUACF.Visible = true;
                    }

                    if (config.ResultsHead)
                    {
                        textBoxHeadCircumF.Visible = true;
                    }

                    if (config.ResultsSSF)
                    {
                        textBoxSSFF.Visible = true;
                    }

                    if (config.ResultsTSF)
                    {
                        textBoxTSFF.Visible = true;
                    }

                    textBoxWHOFlag.Visible = false;
                    labelWHOFlag.Visible = false;
                }
                else if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO1978))
                {
                    textBoxWHOFlag.Visible = true;
                    labelWHOFlag.Visible = true;

                    textBoxHTforAgeF.Visible = false;
                    textBoxBMIF.Visible = false;
                    textBoxWTforAgeF.Visible = false;
                    textBoxWTforHTF.Visible = false;
                    textBoxHeadCircumF.Visible = false;
                    textBoxMUACF.Visible = false;
                    textBoxSSFF.Visible = false;
                    textBoxTSFF.Visible = false;
                }
            }
            else
            {
                labelWHOFlag.Visible = false;
                textBoxWHOFlag.Visible = false;
                textBoxHTforAgeF.Visible = false;
                textBoxBMIF.Visible = false;
                textBoxWTforAgeF.Visible = false;
                textBoxWTforHTF.Visible = false;
                textBoxHeadCircumF.Visible = false;
                textBoxMUACF.Visible = false;
                textBoxSSFF.Visible = false;
                textBoxTSFF.Visible = false;
            }

            // Statistics
            if (config.StatsPercentiles)
            {
                if (config.ResultsHA)
                {
                    textBoxHTforAgeP.Visible = true;
                }

                if (config.ResultsBMI && !config.ReferenceType.Equals(GrowthReferenceTypes.WHO1978))
                {
                    textBoxBMIPercentile.Visible = true;
                }

                if (config.ResultsWA)
                {
                    textBoxWTforAgeP.Visible = true;
                }

                if (config.ResultsWH)
                {
                    textBoxWTforHTP.Visible = true;
                }

                if (config.ResultsSSF && config.ReferenceType.Equals(GrowthReferenceTypes.WHO2006))
                {
                    textBoxSSFP.Visible = true;
                }

                if (config.ResultsTSF && config.ReferenceType.Equals(GrowthReferenceTypes.WHO2006))
                {
                    textBoxTSFP.Visible = true;
                }

                if (config.ResultsHead && !config.ReferenceType.Equals(GrowthReferenceTypes.WHO1978))
                {
                    textBoxHeadCircumP.Visible = true;
                }

                if (config.ResultsArm)
                {
                    textBoxMUACP.Visible = true;
                }
            }
            else
            {                
                textBoxHTforAgeP.Visible = false;
                textBoxBMIPercentile.Visible = false;
                textBoxWTforAgeP.Visible = false;
                textBoxWTforHTP.Visible = false;
                textBoxSSFP.Visible = false;
                textBoxTSFP.Visible = false;
                textBoxHeadCircumP.Visible = false;
                textBoxMUACP.Visible = false;
            }

            // z-scores
            if (config.StatsZScores)
            {
                if (config.ResultsHA)
                {
                    textBoxHTforAgeZ.Visible = true;
                }

                if (config.ResultsBMI && !config.ReferenceType.Equals(GrowthReferenceTypes.WHO1978))
                {
                    textBoxBMIZ.Visible = true;
                }

                if (config.ResultsWA)
                {
                    textBoxWTforAgeZ.Visible = true;
                }

                if (config.ResultsWH)
                {
                    textBoxWTforHTZ.Visible = true;
                }

                if (config.ResultsSSF && config.ReferenceType.Equals(GrowthReferenceTypes.WHO2006))
                {
                    textBoxSSFZ.Visible = true;
                }

                if (config.ResultsTSF && config.ReferenceType.Equals(GrowthReferenceTypes.WHO2006))
                {
                    textBoxTSFZ.Visible = true;
                }

                if (config.ResultsHead && !config.ReferenceType.Equals(GrowthReferenceTypes.WHO1978))
                {
                    textBoxHeadCircumZ.Visible = true;
                }

                if (config.ResultsArm)
                {
                    textBoxMUACZ.Visible = true;
                }
            }
            else
            {
                textBoxHTforAgeZ.Visible = false;
                textBoxBMIZ.Visible = false;
                textBoxWTforAgeZ.Visible = false;
                textBoxWTforHTZ.Visible = false;
                textBoxSSFZ.Visible = false;
                textBoxTSFZ.Visible = false;
                textBoxHeadCircumZ.Visible = false;
                textBoxMUACZ.Visible = false;
            }

            if (config.UnitsArm.Equals(MeasurementUnits.Centimeter.Abbreviation))
            {
                labelUnitsArm.Text = MeasurementUnits.Centimeter.Abbreviation;
            }
            else
            {
                labelUnitsArm.Text = MeasurementUnits.Inch.Abbreviation;
            }

            if (config.UnitsHead.Equals(MeasurementUnits.Centimeter.Abbreviation))
            {
                labelUnitsHead.Text = MeasurementUnits.Centimeter.Abbreviation;
            }
            else
            {
                labelUnitsHead.Text = MeasurementUnits.Inch.Abbreviation;
            }

            if (config.UnitsHeight.Equals(MeasurementUnits.Centimeter.Abbreviation))
            {
                labelUnitsHeight.Text = MeasurementUnits.Centimeter.Abbreviation;
            }
            else
            {
                labelUnitsHeight.Text = MeasurementUnits.Inch.Abbreviation;
            }

            if (config.UnitsSkin.Equals(MeasurementUnits.Millimeter.Abbreviation))
            {
                labelUnitsSSF.Text = MeasurementUnits.Millimeter.Abbreviation;
                labelUnitsTSF.Text = MeasurementUnits.Millimeter.Abbreviation;
            }
            else
            {
                labelUnitsSSF.Text = MeasurementUnits.Inch.Abbreviation;
                labelUnitsTSF.Text = MeasurementUnits.Inch.Abbreviation;
            }

            if (config.UnitsWeight.Equals(MeasurementUnits.Kilogram.Abbreviation))
            {
                labelUnitsWeight.Text = MeasurementUnits.Kilogram.Abbreviation;
                textBoxWeightOz.Visible = false;
                labelOunces.Visible = false;
            }
            else
            {
                labelUnitsWeight.Text = MeasurementUnits.Pound.Abbreviation;
                textBoxWeightOz.Visible = true;
                labelOunces.Visible = true;
            }

            dataGridViewMain.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        } // end ConfigureFormControls()

        protected internal override NutriPatient GuiMediator()
        {
            return patient;
        }

        /// <summary>
        /// Tells the main menu to load a specific program configuration.
        /// </summary>
        /// <param name="configuration">The configuration to be loaded.</param>        
        /// <returns>bool</returns>
        internal override bool LoadConfigFile(NutriConfig configuration)
        {
            try
            {
                this.oldConfig = new NutriConfig(this.config);
                this.config = new NutriConfig(configuration);
            }
            catch (Exception ex)
            {
                MessageBox.Show(SharedStrings.ERROR_CONFIG_FILE_LOAD1 + ex.ToString());
                return false;
            }
            finally
            {
                ConfigureFormControls();
                ConvertMeasurements();
                RefreshData(0);
            }
            return true;
        }
        
        /// <summary>
        /// Sets up the export routine. TODO: Move elsewhere?
        /// </summary>
        /// <param name="filename">The name of the file to be generated</param>
        /// <param name="extension">The file extension to be used</param>
        /// <returns>bool</returns>
        internal bool ExportSetup(ref string fileName, ref string extension)
        {
            return false;            
        } 

        /// <summary>
        /// Shows a grid table of all measurements for a given ID.
        /// </summary>                
        internal void ShowGrid()
        {
            if (!DatabaseLoaded)
            {
                return;
            }

            GridViewForm grid = new GridViewForm(Patient.Database, Patient.Id, Patient.Table.TableName);
            grid.Show();
           
        } // end ShowGrid()
               
        /// <summary>
        /// Tells the Patient object to grab a specific record from the database
        /// </summary>                
        internal void AssignDatabaseValues(bool right, bool full, int id, bool goToId, DateTime date, bool useDate)
        {            
            if (ShowSaveDataPrompt() == false)
            {
                return;
            }

            #region Input Validation
            // Input validation
            try
            {
                if (id <= 0)
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            #endregion

            try
            {
                if (id <= 0)
                {
                    id = Convert.ToInt32(textBoxIDNumber.Text);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            
            if (!full)
                date = dateTimePickerDOM.Value;

            Patient.LoadValuesFromDatabase(right, full, id, goToId, date, useDate);            
            LoadingRecord = true;
            PopulateFormControls();
            LoadingRecord = true;

            UpdateGridView();

        } // end AssignDatabaseValues

        /// <summary>
        /// Grabs the values from the Patient object, and then assigns them to
        /// various form controls.
        /// </summary>                
        protected internal override void PopulateFormControls()
        {
            LoadingRecord = true;

            if (Patient.IsFirstId)
            {
                buttonLeft.Enabled = false;
                buttonLeftFirst.Enabled = false;
            }
            else
            {
                buttonLeft.Enabled = true;
                buttonLeftFirst.Enabled = true;
            }

            if (Patient.IsLastId)
            {
                buttonRight.Enabled = false;
                buttonRightLast.Enabled = false;
            }
            else
            {
                buttonRight.Enabled = true;
                buttonRightLast.Enabled = true;
            }

            textBoxIDNumber.Text = Patient.Id.ToString();
            integerTextBoxCluster.Text = Patient.Cluster;
            integerTextBoxTeam.Text = Patient.Team;
            integerTextBoxHousehold.Text = Patient.Household;
            textBoxFirstName.Text = Patient.FirstName;
            textBoxLastName.Text = Patient.LastName;

            DateTime tempDOB = Patient.BirthDate;

            if (!Patient.UseBirthDate)
            {
                dateTimePickerDOB.Text = NutriStringConstants.Empty;
                dateTimePickerDOB.Checked = false;
                textBoxAgeMonths.ReadOnly = false;
                textBoxAgeYears.ReadOnly = false;                
            }
            else
            {                
                dateTimePickerDOB.Value = Convert.ToDateTime(tempDOB);
                dateTimePickerDOB.Checked = true;
                textBoxAgeMonths.ReadOnly = true;
                textBoxAgeYears.ReadOnly = true;                 
            }

            string age = Patient.Visit.Age;
            textBoxAgeMonths.Text = String.Format("{0:0.00}", age);                         
                     
            dateTimePickerDOM.Value = Patient.Visit.VisitDate;

            // Update Height            
            if (config.UnitsHeight.Equals(MeasurementUnits.Centimeter.Abbreviation))
            {
                textBoxHeight.Text = Patient.Visit.HeightMetric;
            }
            else
            {
                textBoxHeight.Text = Patient.Visit.HeightCustomary;
            }

            // Update Weight            
            if (config.UnitsWeight.Equals(MeasurementUnits.Kilogram.Abbreviation))
            {
                textBoxWeight.Text = Patient.Visit.WeightMetric;
            }
            else
            {
                textBoxWeight.Text = Patient.Visit.WeightCustomary;
            }

            // Update Head circumference            
            if (config.UnitsHead.Equals(MeasurementUnits.Centimeter.Abbreviation))
            {
                textBoxHead.Text = Patient.Visit.HeadCircumferenceMetric;
            }
            else
            {
                textBoxHead.Text = Patient.Visit.HeadCircumferenceCustomary;
            }

            // MUAC updated                        
            if (config.UnitsArm.Equals(MeasurementUnits.Centimeter.Abbreviation))
            {
                textBoxMUAC.Text = Patient.Visit.ArmCircumferenceMetric;
            }
            else
            {
                textBoxMUAC.Text = Patient.Visit.ArmCircumferenceCustomary;
            }

            // Subscapular skin fold            
            if (config.UnitsSkin.Equals(MeasurementUnits.Millimeter.Abbreviation))
            {
                textBoxSSF.Text = Patient.Visit.SubscapularSkinFoldMetric;
            }
            else
            {
                textBoxSSF.Text = Patient.Visit.SubscapularSkinFoldCustomary;
            }

            // Triceps skin fold            
            if (config.UnitsSkin.Equals(MeasurementUnits.Millimeter.Abbreviation))
            {
                textBoxTSF.Text = Patient.Visit.TricepsSkinFoldMetric;
            }
            else
            {
                textBoxTSF.Text = Patient.Visit.TricepsSkinFoldCustomary;
            }

            textBoxNotes.Text = Patient.Visit.Notes;

            if (Patient.Gender.Equals("F"))
            {
                radioButtonMale.Checked = false;
                radioButtonFemale.Checked = true;                
            }
            else
            {
                radioButtonFemale.Checked = false;
                radioButtonMale.Checked = true;                
            }

            if (Patient.Visit.Edema)
            {
                checkBoxEdema.Checked = true;
            }
            else
            {
                checkBoxEdema.Checked = false;                
            }

            if (Patient.Visit.Recumbent)
            {
                checkBoxRecumbent.Checked = true;
            }
            else
            {
                checkBoxRecumbent.Checked = false;              
            }

            string BMI = Patient.Visit.BMI;
            textBoxBMI.Text = NutriPatient.FormatNumber(BMI, config.PrecisionZ);

            // Assign results and statistics
            if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO1978))
            {                
                textBoxWHOFlag.Text = Patient.Visit.WHO1978Flag;
                textBoxWTforAgeP.Text = Patient.Visit.WHO1978WAC;
                textBoxWTforAgeZ.Text = Patient.Visit.WHO1978WAZ;

                textBoxWTforHTP.Text = Patient.Visit.WHO1978WHC;
                textBoxWTforHTZ.Text = Patient.Visit.WHO1978WHZ;

                textBoxHTforAgeP.Text = Patient.Visit.WHO1978HAC;
                textBoxHTforAgeZ.Text = Patient.Visit.WHO1978HAZ;

                textBoxSSFP.Text = NutriStringConstants.Undefined;
                textBoxSSFZ.Text = NutriStringConstants.Undefined;

                textBoxTSFP.Text = NutriStringConstants.Undefined;
                textBoxTSFZ.Text = NutriStringConstants.Undefined;

                textBoxHeadCircumP.Text = NutriStringConstants.Undefined;
                textBoxHeadCircumZ.Text = NutriStringConstants.Undefined;

                textBoxBMIPercentile.Text = NutriStringConstants.Undefined;
                textBoxBMIZ.Text = NutriStringConstants.Undefined;

                textBoxMUACP.Text = NutriStringConstants.Undefined;
                textBoxMUACZ.Text = NutriStringConstants.Undefined;
            }

            else if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO2006))
            {                
                textBoxWTforAgeP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006WAC, config.PrecisionC);
                textBoxWTforAgeZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006WAZ, config.PrecisionZ);

                textBoxWTforHTP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006WHC, config.PrecisionC);
                textBoxWTforHTZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006WHZ, config.PrecisionZ);

                textBoxHTforAgeP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006HAC, config.PrecisionC);
                textBoxHTforAgeZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006HAZ, config.PrecisionZ);

                textBoxSSFP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006SSFC, config.PrecisionC);
                textBoxSSFZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006SSFZ, config.PrecisionZ);

                textBoxTSFP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006TSFC, config.PrecisionC);
                textBoxTSFZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006TSFZ, config.PrecisionZ);

                textBoxHeadCircumP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006HCircumC, config.PrecisionC);
                textBoxHeadCircumZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006HCircumZ, config.PrecisionZ);

                textBoxBMIPercentile.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006BMIC, config.PrecisionC);
                textBoxBMIZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006BMIZ, config.PrecisionZ);                

                textBoxMUACP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006MUACC, config.PrecisionC);
                textBoxMUACZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2006MUACZ, config.PrecisionZ);
            }

            else if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO2007))
            {
                textBoxWTforAgeP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2007WAC, config.PrecisionC);
                textBoxWTforAgeZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2007WAZ, config.PrecisionZ);

                textBoxWTforHTP.Text = NutriStringConstants.Undefined;
                textBoxWTforHTZ.Text = NutriStringConstants.Undefined;

                textBoxHTforAgeP.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2007HAC, config.PrecisionC);
                textBoxHTforAgeZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2007HAZ, config.PrecisionZ);

                textBoxSSFP.Text = NutriStringConstants.Undefined;
                textBoxSSFZ.Text = NutriStringConstants.Undefined;

                textBoxTSFP.Text = NutriStringConstants.Undefined;
                textBoxTSFZ.Text = NutriStringConstants.Undefined;

                textBoxHeadCircumP.Text = NutriStringConstants.Undefined;
                textBoxHeadCircumZ.Text = NutriStringConstants.Undefined;

                textBoxBMIPercentile.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2007BMIC, config.PrecisionC);
                textBoxBMIZ.Text = NutriPatient.FormatNumber(Patient.Visit.WHO2007BMIZ, config.PrecisionZ);

                textBoxMUACP.Text = NutriStringConstants.Undefined;
                textBoxMUACZ.Text = NutriStringConstants.Undefined;
            }

            else if (config.ReferenceType.Equals(GrowthReferenceTypes.CDC2000))
            {                
                textBoxWTforAgeP.Text = NutriPatient.FormatNumber(Patient.Visit.CDCWAC, config.PrecisionC);
                textBoxWTforAgeZ.Text = NutriPatient.FormatNumber(Patient.Visit.CDCWAZ, config.PrecisionZ);

                textBoxWTforHTP.Text = NutriPatient.FormatNumber(Patient.Visit.CDCWHC, config.PrecisionC);
                textBoxWTforHTZ.Text = NutriPatient.FormatNumber(Patient.Visit.CDCWHZ, config.PrecisionZ);

                textBoxHTforAgeP.Text = NutriPatient.FormatNumber(Patient.Visit.CDCHAC, config.PrecisionC);
                textBoxHTforAgeZ.Text = NutriPatient.FormatNumber(Patient.Visit.CDCHAZ, config.PrecisionZ);

                textBoxSSFP.Text = NutriStringConstants.Undefined;
                textBoxSSFZ.Text = NutriStringConstants.Undefined;

                textBoxTSFP.Text = NutriStringConstants.Undefined;
                textBoxTSFZ.Text = NutriStringConstants.Undefined;

                textBoxHeadCircumP.Text = NutriPatient.FormatNumber(Patient.Visit.CDCHCircumC, config.PrecisionC);
                textBoxHeadCircumZ.Text = NutriPatient.FormatNumber(Patient.Visit.CDCHCircumZ, config.PrecisionZ);

                textBoxBMIPercentile.Text = NutriPatient.FormatNumber(Patient.Visit.CDCBMIC, config.PrecisionC);
                textBoxBMIZ.Text = NutriPatient.FormatNumber(Patient.Visit.CDCBMIZ, config.PrecisionZ);

                textBoxMUACP.Text = NutriStringConstants.Undefined;
                textBoxMUACZ.Text = NutriStringConstants.Undefined;

                textBoxHTforAgeF.Text = CDC2000GrowthReference.CheckHeightAgeFlagged(Patient.Visit.CDCHAFlag);
                textBoxWTforAgeF.Text = CDC2000GrowthReference.CheckWeightAgeFlagged(Patient.Visit.CDCWAFlag);
                textBoxWTforHTF.Text = CDC2000GrowthReference.CheckWeightHeightFlagged(Patient.Visit.CDCWHFlag);
                textBoxBMIF.Text = CDC2000GrowthReference.CheckBMIFlagged(Patient.Visit.CDCBMIFlag);
            }

            textBoxMUACAge.Text = Patient.Visit.MUACAgeZ;
            textBoxMUACHeight.Text = Patient.Visit.MUACHeightZ;

            UpdateFlags();
            CheckResultsForNullValues();

            // reset our valueChanged var for the next record; very important!
            InputsUpdated = false;
            PatientInfoChanged = false;
            OutputsUpdated = false;            
            LoadingRecord = false;           

        } // end AssignDatabaseValues()         
        #endregion Public Methods

        #region Protected Methods
        #endregion Protected Methods

        #region Private Methods
        /// <summary>
        /// Updates the dataGridView in the main menu.
        /// </summary>
        private void UpdateGridView()
        {
            string tableName = Patient.Table.TableName;

            Query selectQuery = Patient.Database.CreateQuery("select * from " + tableName + " where [fldIdNo] = @Id");            
            selectQuery.Parameters.Add(new QueryParameter("@Id", DbType.Int32, Convert.ToInt32(textBoxIDNumber.Text)));

            DataTable showtable = Patient.Database.Select(selectQuery);

            showtable.Locale = System.Globalization.CultureInfo.InvariantCulture;

            bindingSourcePrimary.DataSource = showtable;
            
            int rows = showtable.Rows.Count;

            dataGridViewMain.ReadOnly = true;    // Don't let users modify anything!

            // Bind the data to the grid control
            dataGridViewMain.DataSource = bindingSourcePrimary;

            //dataGridViewPrimary.Font = new Font("Verdana", 8.0f);

            // Downsize the columns as appropriate to their actual width
            // Without this, we get something like 'Edema' taking up a massive amount of width
            dataGridViewMain.Columns.Remove(NutriStringConstants.ColumnLastName);
            dataGridViewMain.Columns.Remove(NutriStringConstants.ColumnFirstName);
            dataGridViewMain.Columns.Remove("fldCluster");
            dataGridViewMain.Columns.Remove("fldTeam");
            dataGridViewMain.Columns.Remove("fldMother");
            dataGridViewMain.Columns.Remove("fldFather");
            dataGridViewMain.Columns.Remove("fldAddress");
            dataGridViewMain.Columns.Remove("fldNotes");
            dataGridViewMain.Columns.Remove("fldBirthDate");
            dataGridViewMain.Columns.Remove(NutriStringConstants.ColumnSex);
            /*
            if (config.UnitsHeight.Equals(MeasurementUnits.Centimeter.Abbreviation))
            {
                dataGridViewMain.Columns.Remove(NutriStringConstants.ColumnHeadCustomary);
            }
            else
            {
                dataGridViewMain.Columns.Remove(NutriStringConstants.ColumnHeightMetric);
            }

            if (config.UnitsWeight.Equals(MeasurementUnits.Kilogram.Abbreviation))
            {
                dataGridViewMain.Columns.Remove(NutriStringConstants.ColumnWeightCustomary);
                dataGridViewMain.Columns.Remove(NutriStringConstants.ColumnWeightOzs);
            }
            else
            {
                dataGridViewMain.Columns.Remove(NutriStringConstants.ColumnWeightMetric);
            }
            */
            for (int i = 0; i < dataGridViewMain.Columns.Count; i++)
            {
                dataGridViewMain.Columns[i].HeaderText = dataGridViewMain.Columns[i].HeaderText.Replace("fld", string.Empty);
            }

            dataGridViewMain.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;                        
            //dt.Dispose();
            showtable.Dispose();

            HighlightGrid();
        }

        /// <summary>
        /// Highlights the row in the grid that corresponds to the current date of measurement
        /// </summary>
        private void HighlightGrid()
        {
            if (!DatabaseLoaded)
                return;

            int rows = dataGridViewMain.Rows.Count;            
            for (int i = 0; i < rows; i++)
            {
                if (dateTimePickerDOM.Text == Convert.ToDateTime(dataGridViewMain.Rows[i].Cells[1].Value).ToShortDateString().ToString())
                {
                    dataGridViewMain.Rows[i].Selected = true;
                }
                else
                {
                    dataGridViewMain.Rows[i].Selected = false;
                }
            }
        }

        /// <summary>
        /// Adds color to the flag boxes. Red is used for H/L, standard colors for OK or missing.
        /// </summary>
        private void UpdateFlags()
        {
            textBoxHTforAgeF.ForeColor = uiBlack;
            textBoxWTforAgeF.ForeColor = uiBlack;
            textBoxWTforHTF.ForeColor = uiBlack;
            textBoxBMIF.ForeColor = uiBlack;
            textBoxHeadCircumF.ForeColor = uiBlack;
            textBoxSSFF.ForeColor = uiBlack;
            textBoxTSFF.ForeColor = uiBlack;
            textBoxMUACF.ForeColor = uiBlack;

            textBoxHTforAgeZ.ForeColor = uiBlack;
            textBoxHTforAgeP.ForeColor = uiBlack;
            textBoxWTforAgeZ.ForeColor = uiBlack;
            textBoxWTforAgeP.ForeColor = uiBlack;
            textBoxWTforHTZ.ForeColor = uiBlack;
            textBoxWTforHTP.ForeColor = uiBlack;
            textBoxBMI.ForeColor = uiBlack;
            textBoxBMIZ.ForeColor = uiBlack;
            textBoxBMIPercentile.ForeColor = uiBlack;
            textBoxHeadCircumZ.ForeColor = uiBlack;
            textBoxHeadCircumP.ForeColor = uiBlack;
            textBoxSSFZ.ForeColor = uiBlack;
            textBoxSSFP.ForeColor = uiBlack;
            textBoxTSFZ.ForeColor = uiBlack;
            textBoxTSFP.ForeColor = uiBlack;
            textBoxMUACZ.ForeColor = uiBlack;
            textBoxMUACP.ForeColor = uiBlack;

            textBoxHTforAgeZ.BackColor = Color.FromName("Info");
            textBoxHTforAgeP.BackColor = Color.FromName("Info");
            textBoxWTforAgeZ.BackColor = Color.FromName("Info");
            textBoxWTforAgeP.BackColor = Color.FromName("Info");
            textBoxWTforHTZ.BackColor = Color.FromName("Info");
            textBoxWTforHTP.BackColor = Color.FromName("Info");
            textBoxBMI.BackColor = Color.FromName("Info");
            textBoxBMIZ.BackColor = Color.FromName("Info");
            textBoxBMIPercentile.BackColor = Color.FromName("Info");
            textBoxHeadCircumZ.BackColor = Color.FromName("Info");
            textBoxHeadCircumP.BackColor = Color.FromName("Info");
            textBoxSSFZ.BackColor = Color.FromName("Info");
            textBoxSSFP.BackColor = Color.FromName("Info");
            textBoxTSFZ.BackColor = Color.FromName("Info");
            textBoxTSFP.BackColor = Color.FromName("Info");
            textBoxMUACZ.BackColor = Color.FromName("Info");
            textBoxMUACP.BackColor = Color.FromName("Info");
            
                textBoxHTforAgeF.BackColor = Color.FromName("Info");
                textBoxWTforAgeF.BackColor = Color.FromName("Info");
                textBoxWTforHTF.BackColor = Color.FromName("Info");
                textBoxBMIF.BackColor = Color.FromName("Info");
                textBoxHeadCircumF.BackColor = Color.FromName("Info");
                textBoxSSFF.BackColor = Color.FromName("Info");
                textBoxTSFF.BackColor = Color.FromName("Info");
                textBoxMUACF.BackColor = Color.FromName("Info");            

            if (textBoxHTforAgeF.Text.Equals(NutriStringConstants.H) || textBoxHTforAgeF.Text.Equals(NutriStringConstants.L))
                textBoxHTforAgeF.BackColor = uiRed;
            if (textBoxWTforAgeF.Text.Equals(NutriStringConstants.H) || textBoxWTforAgeF.Text.Equals(NutriStringConstants.L))
                textBoxWTforAgeF.BackColor = uiRed;
            if (textBoxWTforHTF.Text.Equals(NutriStringConstants.H) || textBoxWTforHTF.Text.Equals(NutriStringConstants.L))
                textBoxWTforHTF.BackColor = uiRed;
            if (textBoxBMIF.Text.Equals(NutriStringConstants.H) || textBoxBMIF.Text.Equals(NutriStringConstants.L))
                textBoxBMIF.BackColor = uiRed;
            if (textBoxHeadCircumF.Text.Equals(NutriStringConstants.H) || textBoxHeadCircumF.Text.Equals(NutriStringConstants.L))
                textBoxHeadCircumF.BackColor = uiRed;
            if (textBoxSSFF.Text.Equals(NutriStringConstants.H) || textBoxSSFF.Text.Equals(NutriStringConstants.L))
                textBoxSSFF.BackColor = uiRed;
            if (textBoxTSFF.Text.Equals(NutriStringConstants.H) || textBoxTSFF.Text.Equals(NutriStringConstants.L))
                textBoxTSFF.BackColor = uiRed;
            if (textBoxMUACF.Text.Equals(NutriStringConstants.H) || textBoxMUACF.Text.Equals(NutriStringConstants.L))
                textBoxMUACF.BackColor = uiRed;

            #region Color Coded Output
            if (config.ColorCoding != "0")
            {                
            }
            #endregion Color Coded Output

        } // end UpdateFlags()

        /// <summary>
        /// Checks the date of measurement and date of birth to ensure there aren't
        /// any errors - e.g. the date of measurement is prior to the date of birth.
        /// </summary>
        private void ValidateDates()
        {
            if (LoadingRecord)
            {
                return;
            }

            bool dobActive = dateTimePickerDOB.Checked;

            // Having a DOB that is after the date of measurement is a problem. We
            // need to check for this!
            if ((dateTimePickerDOM.Value < dateTimePickerDOB.Value) && dobActive)
            {
                MessageBox.Show(SharedStrings.WARNING_DATE_CONFLICT1, SharedStrings.WARNING_DATE_CONFLICT1_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                dateTimePickerDOB.Focus();
                dateTimePickerDOB.Checked = false;

                // We want to end here so that we don't end up with negative values! This
                // forces the user to enter something valid before invalid data can be
                // shown on the form.
                return;
            }
            else if (!dobActive)
            {
                // No sense in calculating dates if the box is unchecked.
                return;

            } // end if            

            DateTime origin = dateTimePickerDOB.Value;
            DateTime current = dateTimePickerDOM.Value;

            TimeSpan diff = current.Subtract(origin);
            double days = diff.Days;
            double years = days / 365.25; // The .25 accounts for leap years
            double months = years * 12;

            string ageMonths = NutriStringConstants.Empty;

            if (months >= 0.0)
            {
                ageMonths = String.Format("{0:0.00}", months);
            }

            textBoxAgeMonths.Text = ageMonths;

            RefreshData(1);
        } // end ValidateDates() 

        /// <summary>
        /// Checks to see if text boxes in results section have null values; if so,
        /// assigns "Undefined" to them instead.
        /// </summary>
        private void CheckResultsForNullValues()
        {
            if (string.IsNullOrEmpty(textBoxHeadCircumP.Text) || textBoxHeadCircumP.Text.Equals(NutriStringConstants.Null))
                textBoxHeadCircumP.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxHeadCircumZ.Text) || textBoxHeadCircumZ.Text.Equals(NutriStringConstants.Null))
                textBoxHeadCircumZ.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxHTforAgeP.Text) || textBoxHTforAgeP.Text.Equals(NutriStringConstants.Null))
                textBoxHTforAgeP.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxHTforAgeZ.Text) || textBoxHTforAgeZ.Text.Equals(NutriStringConstants.Null))
                textBoxHTforAgeZ.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxWTforAgeP.Text) || textBoxWTforAgeP.Text.Equals(NutriStringConstants.Null))
                textBoxWTforAgeP.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxWTforAgeZ.Text) || textBoxWTforAgeZ.Text.Equals(NutriStringConstants.Null))
                textBoxWTforAgeZ.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxWTforHTP.Text) || textBoxWTforHTP.Text.Equals(NutriStringConstants.Null))
                textBoxWTforHTP.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxWTforHTZ.Text) || textBoxWTforHTZ.Text.Equals(NutriStringConstants.Null))
                textBoxWTforHTZ.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxBMIPercentile.Text) || textBoxBMIPercentile.Text.Equals(NutriStringConstants.Null))
                textBoxBMIPercentile.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxBMIZ.Text) || textBoxBMIZ.Text.Equals(NutriStringConstants.Null))
                textBoxBMIZ.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxBMI.Text) || textBoxBMI.Text.Equals(NutriStringConstants.Null))
                textBoxBMI.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxMUACZ.Text) || textBoxMUACZ.Text.Equals(NutriStringConstants.Null))
                textBoxMUACZ.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxMUACP.Text) || textBoxMUACP.Text.Equals(NutriStringConstants.Null))
                textBoxMUACP.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxSSFP.Text) || textBoxSSFP.Text.Equals(NutriStringConstants.Null))
                textBoxSSFP.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxSSFZ.Text) || textBoxSSFZ.Text.Equals(NutriStringConstants.Null))
                textBoxSSFZ.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxTSFP.Text) || textBoxTSFP.Text.Equals(NutriStringConstants.Null))
                textBoxTSFP.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxTSFZ.Text) || textBoxTSFZ.Text.Equals(NutriStringConstants.Null))
                textBoxTSFZ.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxMUACHeight.Text) || textBoxMUACHeight.Text.Equals(NutriStringConstants.Null))
                textBoxMUACHeight.Text = NutriStringConstants.Undefined;

            if (string.IsNullOrEmpty(textBoxMUACAge.Text) || textBoxMUACAge.Text.Equals(NutriStringConstants.Null))
                textBoxMUACAge.Text = NutriStringConstants.Undefined;

        } // end CheckResultsForNullValues()

        /// <summary>
        /// Saves the data from the form to the database. If the data is not saved to the 
        /// database, then we return false so the user can be shown an error message.
        /// </summary>        
        /// <returns>bool</returns>
        private bool SaveData()
        {
            if (DatabaseLoaded == false)
            {
                return false;
            }

            RefreshData(0);

            if (dateTimePickerDOM.Focused)
            {
                ValidateDates();
            }

            string updateType = "1";

            // This should never be NULL since the 'key' is the ID + DOM...            
            string temp = String.Format("{0:G}", dateTimePickerDOM.Text);

            string DOB = NutriStringConstants.Null;
            if (dateTimePickerDOB.Checked)
            {
                DOB = String.Format("{0:G}", dateTimePickerDOB.Text);
            }

            Patient.Id = Convert.ToInt32(textBoxIDNumber.Text);
            Patient.Cluster = integerTextBoxCluster.Text;
            Patient.Team = integerTextBoxTeam.Text;
            Patient.Household = integerTextBoxHousehold.Text;
            Patient.FirstName = textBoxFirstName.Text;
            Patient.LastName = textBoxLastName.Text;
            Patient.BirthDate = dateTimePickerDOB.Value;
            Patient.Visit.Age = textBoxAgeMonths.Text;            
            Patient.Visit.VisitDate = dateTimePickerDOM.Value;

            Patient.Visit.Notes = textBoxNotes.Text;

            if (radioButtonMale.Checked)
            {
                Patient.Gender = "M";
            }
            else
            {
                Patient.Gender = "F";
            }

            if (checkBoxEdema.Checked)
            {
                Patient.Visit.Edema = true;
            }
            else
            {
                Patient.Visit.Edema = false;
            }

            if (checkBoxRecumbent.Checked)
            {
                Patient.Visit.Recumbent = true;
            }
            else
            {
                Patient.Visit.Recumbent = false;
            }

            Patient.Visit.BMI = textBoxBMI.Text;

            if (!dateTimePickerDOB.Checked)
            {
                Patient.UseBirthDate = false;
            }
            else
            {
                Patient.UseBirthDate = true;
            }


            bool fullUpdate = PatientInfoChanged; // If patient info was changed (name, dob, gender) then we need
            // to do a full update.

            if (fullUpdate && Patient.HasMultipleVisits())
            {
                DialogResult result = MessageBox.Show(SharedStrings.NOTICE_PATIENT_INFO_CHANGED,
                        SharedStrings.NOTICE_PATIENT_INFO_CHANGED_TITLE, MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                if (result == DialogResult.No)
                {
                    return false;
                }
                else
                {
                    updateType = "0";
                }
            }

            bool saved = Patient.SaveData(updateType);
            if (!saved)
            {
                MessageBox.Show(SharedStrings.SAVE_NOT_SUCCESSFUL);
            }
            else
            {
                UpdateGridView();
            }

            return true;

        } // end SaveData()

        /// <summary>
        /// Prompts the user whether or not they want to save the current record.
        /// </summary>        
        /// <returns>bool</returns>
        private bool ShowSaveDataPrompt()
        {

            // There are three possible results from this prompt: User presses YES and data is saved, and whatever
            // action prompted the save (such as them trying to create a new record) is allowed to proceed; User
            // presses NO and data is not saved, and whatever action prompted the save is allowed to proceed; User
            // presses CANCEL and data is not saved, and whatever action prompted the save is halted.

            // If we return true, the calling action will continue. If false, it will not continue. Thus a FALSE
            // signifies a cancel, and a true could be either a Yes or No. We check if the prompt was a Yes,
            // and if so, we do a SaveData() call. If the prompt was not a Yes or a Cancel, we assume it was a No,
            // and therefore we return true - that is, we tell the function that called us to proceed, but notice
            // that we don't do a SaveData() call of our own. This gets the effect we desire.

            // Must check to see whether something has been updated, and if so, prompt the user
            // to save the record before loading a new one. This is Epi 3 behavior.
            if (InputsUpdated && DatabaseLoaded)
            {
                DialogResult result = MessageBox.Show(SharedStrings.NOTICE_RECORD_MODIFIED,
                    SharedStrings.NOTICE_RECORD_MODIFIED_TITLE, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                // If we get an acknowledgement on our message box, then run SaveData()
                if (result == DialogResult.Yes)
                {
                    SaveData();
                    return true;
                }
                else if (result == DialogResult.Cancel)
                {
                    // If they click cancel, nothing should happen; the record is not saved
                    // and they do not go forward or backwards.
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// Loads the proper visit date into the form controls depending on which row has been selected in the grid.
        /// </summary>
        private void GridRowClicked()
        {
            try
            {
                // Create a data grid row and assign it the value of CurrentRow, which is the
                // currently-selected row.
                DataGridViewRow row = dataGridViewMain.CurrentRow;

                // Make sure we don't do this for the last row, which is always blank
                int lastRow = dataGridViewMain.Rows.Count - 1;
                if (row.Equals(dataGridViewMain.Rows[lastRow]))
                {
                    return;
                }

                // Get our collection of cells, which should be all the cells in this row
                DataGridViewCellCollection cells = row.Cells;

                // The first two columns should always be the ID and the current date, so we
                // take those two values from our cell array and assign them to temp vars;
                // we need to do some conversions here as well.
                int id = Convert.ToInt32(cells[0].Value);
                DateTime date = Convert.ToDateTime(cells[1].Value);
                this.AssignDatabaseValues(false, true, id, true, date, true);
            }
            catch (Exception ex)
            {
                // Catch our exception.
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// Displays a graph showing the patient's measurement for the currently-selected visit
        /// </summary>
        private void DisplayGraphOptions()
        {
            if (!DatabaseLoaded)
            {
                return;
            }
            
            ChartOptionsDialog chartDialog = new ChartOptionsDialog(config);
            chartDialog.ShowDialog(this);

            string result = chartDialog.Result;
            if (result.Equals(string.Empty))
            {
                return;
            }
            else
            {
                DisplayGraph(result);
            }            
        }

        /// <summary>
        /// Displays a graph showing the patient's measurements for all visits they have made.
        /// </summary>
        private void DisplayGraph(string result)
        {
            if (!DatabaseLoaded)
            {
                return;
            }

            #region Input Validation
            if (result.Equals(string.Empty) || result.Length > 155)
            {
                throw new Exception();
            }
            #endregion Input Validation

            if (config.ReferenceType.Equals(GrowthReferenceTypes.CDC2000))
            {                
                string measurement = MeasurementOptions.BMI.Abbreviation;
                measurement = result.ToString();

                MeasurementOption measurementOption = MeasurementOptions.BMI;
                if (measurement.Equals(MeasurementOptions.BMI.Abbreviation))
                {
                    measurementOption = MeasurementOptions.BMI;
                }
                else if (measurement.Equals(MeasurementOptions.HA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.HA;
                }
                else if (measurement.Equals(MeasurementOptions.HCA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.HCA;
                }
                else if (measurement.Equals(MeasurementOptions.LA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.LA;
                }
                else if (measurement.Equals(MeasurementOptions.WA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WA;
                }
                else if (measurement.Equals(MeasurementOptions.WH.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WH;
                }
                else if (measurement.Equals(MeasurementOptions.WL.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WL;
                }
                else
                {
                    throw new Exception();
                }

                string gender = "male";
                if (radioButtonFemale.Checked)
                {
                    gender = "female";
                }

                string name = string.Empty;
                // If the configuration has names enabled, then show them in the graph...
                if (config.Name && textBoxLastName.Text.Length > 0 && textBoxFirstName.Text.Length > 0)
                {
                    name = textBoxFirstName.Text + " " + textBoxLastName.Text;
                }
                // ... otherwise, don't display them on the chart!!! (privacy issues, etc)
                else
                {
                    name = textBoxIDNumber.Text;
                    if (textBoxIDNumber.Text.Length <= 0)
                    {
                        name = "n/a";
                    }
                }

                ProcessStartInfo proc = new ProcessStartInfo();
                proc.WindowStyle = ProcessWindowStyle.Normal;
                proc.CreateNoWindow = true;
                proc.FileName = "NutriChart.exe";
                string points = Patient.GetDataPointsForCharting(measurementOption, config.ReferenceType, "P");
                // Format: args[0] is the path, [1] is name, [2] is gender, [3] is measurement, [4] is ref type (e.g. CDC), [5] specifies whether it's a percentile or z-score, [6] is age, [7] is measurement units
                proc.Arguments = "\"" + name + "\" \"" + gender + "\" \"" + measurement + "\" \"CDC\" \"C\" " + points;

                Process.Start(proc);
            }

            else if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO2006))
            {
                string measurement = MeasurementOptions.BMI.Abbreviation;
                measurement = result.ToString();

                MeasurementOption measurementOption = MeasurementOptions.BMI;
                if (measurement.Equals(MeasurementOptions.BMI.Abbreviation))
                {
                    measurementOption = MeasurementOptions.BMI;
                }
                else if (measurement.Equals(MeasurementOptions.HA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.HA;
                }
                else if (measurement.Equals(MeasurementOptions.HCA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.HCA;
                }
                else if (measurement.Equals(MeasurementOptions.LA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.LA;
                }
                else if (measurement.Equals(MeasurementOptions.WA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WA;
                }
                else if (measurement.Equals(MeasurementOptions.WH.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WH;
                }
                else if (measurement.Equals(MeasurementOptions.WL.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WL;
                }
                else if (measurement.Equals(MeasurementOptions.SSFA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.SSFA;
                }
                else if (measurement.Equals(MeasurementOptions.TSFA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.TSFA;
                }
                else if (measurement.Equals(MeasurementOptions.MUACA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.MUACA;
                }
                else
                {
                    throw new Exception();
                }

                string gender = "male";
                if (radioButtonFemale.Checked)
                {
                    gender = "female";
                }

                string name = string.Empty;
                // If the configuration has names enabled, then show them in the graph...
                if (config.Name && textBoxLastName.Text.Length > 0 && textBoxFirstName.Text.Length > 0)
                {
                    name = textBoxFirstName.Text + " " + textBoxLastName.Text;
                }
                // ... otherwise, don't display them on the chart!!! (privacy issues, etc)
                else
                {
                    name = textBoxIDNumber.Text;
                    if (textBoxIDNumber.Text.Length <= 0)
                    {
                        name = "n/a";
                    }
                }

                ProcessStartInfo proc = new ProcessStartInfo();
                proc.WindowStyle = ProcessWindowStyle.Normal;
                proc.CreateNoWindow = true;
                proc.FileName = "NutriChart.exe";
                string points = Patient.GetDataPointsForCharting(measurementOption, config.ReferenceType, "P");
                // Format: args[0] is the path, [1] is name, [2] is gender, [3] is measurement, [4] is ref type (e.g. CDC), [5] specifies whether it's a percentile or z-score, [6] is age, [7] is measurement units
                proc.Arguments = "\"" + name + "\" \"" + gender + "\" \"" + measurement + "\" \"WHO2006\" \"C\" " + points;

                Process.Start(proc);
            }

            else if (config.ReferenceType.Equals(GrowthReferenceTypes.WHO1978))
            {
                string measurement = MeasurementOptions.HA.Abbreviation;
                measurement = result.ToString();

                MeasurementOption measurementOption = MeasurementOptions.HA;
                if (measurement.Equals(MeasurementOptions.HA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.HA;
                }
                else if (measurement.Equals(MeasurementOptions.LA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.LA;
                }
                else if (measurement.Equals(MeasurementOptions.WA.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WA;
                }
                else if (measurement.Equals(MeasurementOptions.WH.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WH;
                }
                else if (measurement.Equals(MeasurementOptions.WL.Abbreviation))
                {
                    measurementOption = MeasurementOptions.WL;
                }
                else
                {
                    throw new Exception();
                }

                string gender = "male";
                if (radioButtonFemale.Checked)
                {
                    gender = "female";
                }

                string name = string.Empty;
                // If the configuration has names enabled, then show them in the graph...
                if (config.Name && textBoxLastName.Text.Length > 0 && textBoxFirstName.Text.Length > 0)
                {
                    name = textBoxFirstName.Text + " " + textBoxLastName.Text;
                }
                // ... otherwise, don't display them on the chart!!! (privacy issues, etc)
                else
                {
                    name = textBoxIDNumber.Text;
                    if (textBoxIDNumber.Text.Length <= 0)
                    {
                        name = "n/a";
                    }
                }

                ProcessStartInfo proc = new ProcessStartInfo();
                proc.WindowStyle = ProcessWindowStyle.Normal;
                proc.CreateNoWindow = true;
                proc.FileName = "NutriChart.exe";
                string points = Patient.GetDataPointsForCharting(measurementOption, config.ReferenceType, "P");
                // Format: args[0] is the path, [1] is name, [2] is gender, [3] is measurement, [4] is ref type (e.g. CDC), [5] specifies whether it's a percentile or z-score, [6] is age, [7] is measurement units
                proc.Arguments = "\"" + name + "\" \"" + gender + "\" \"" + measurement + "\" \"WHO1978\" \"C\" " + points;

                Process.Start(proc);
            }
        }

        /// <summary>
        /// When called, updates the form's status bar.
        /// </summary>
        protected override void UpdateStatusBar()
        {
            base.UpdateStatusBar();
            // If we don't have a database open, stop
            if (!DatabaseLoaded)
            {
                return;
            }

            tsslRecordCount.Text = string.Format(SharedStrings.RECORDS, Patient.GetRecordCount().ToString());
        } // end UpdateStatusBar()

        /// <summary>
        /// Creates a new measurement for an existing child. Will insert a new, mostly-blank record into the 
        /// database and then make that record visible on the screen for editing.
        /// </summary>        
        /// <returns>bool</returns>
        private bool AddNewMeasurement()
        {
            Patient.AddNewMeasurement();

            //AssignDatabaseValues(false, false, Patient.Id, true, Patient.Visit.VisitDate, true);
            PopulateFormControls();

            textBoxLastName.Focus();
            textBoxLastName.Select();

            dateTimePickerDOB.Checked = false;
            textBoxAgeMonths.ReadOnly = false;
            textBoxAgeYears.ReadOnly = false;

            // Need this so that the record count is changed appropriately
            UpdateStatusBar();
            UpdateGridView();

            return true;
        }

        /// <summary>
        /// Creates a new patient. Will insert a new, mostly-blank record into the database and then make 
        /// that record visible on the screen for editing.
        /// </summary>        
        /// <returns>bool</returns>
        private bool AddNewID()
        {
            Patient.AddNewID(false);

            AssignDatabaseValues(false, false, Patient.Id, true, DateTime.Today, false);

            dateTimePickerDOB.Checked = false;
            textBoxAgeMonths.ReadOnly = false;
            textBoxAgeYears.ReadOnly = false;

            // Need this so that the record count is changed appropriately
            UpdateStatusBar();
            UpdateGridView();

            return true;
        } // end AddNewID()

        /// <summary>
        /// When called, calculates the MUAC z-for-age and MUAC z-for-height.
        /// </summary>
        private void CalcMUAC()
        {
            try
            {
                string MUAC = textBoxMUAC.Text;

                if (MUAC == NutriStringConstants.Empty)
                {
                    textBoxMUACAge.Text = NutriStringConstants.Empty;
                    textBoxMUACHeight.Text = NutriStringConstants.Empty;
                    return; // do nothing, the user hasn't given us any input
                }
                double age = -1;
                if (textBoxAgeMonths.Text.Length > 0)
                {
                    age = Convert.ToDouble(textBoxAgeMonths.Text);
                }

                double cm = Convert.ToDouble(textBoxMUAC.Text);
                double height = Convert.ToDouble(textBoxHeight.Text);

                if (config.UnitsArm.Equals(MeasurementUnits.Inch.Abbreviation))
                {
                    height = height * 2.54; // for conversion to cm
                    cm = cm * 2.54; // for conversion to cm
                }

                // Special note: MUAC values are between 65 and 145 cm in height
                if (height < 65 || height > 145 || textBoxMUAC.Text.Length <= 0)
                {
                    textBoxMUACHeight.Text = NutriStringConstants.Undefined;
                }

                if (cm < 10 || cm > 38 || textBoxMUAC.Text.Length <= 0)
                {
                    textBoxMUACHeight.Text = NutriStringConstants.Undefined;
                }

                if (age < 6 || age > 59 || textBoxAgeMonths.Text.Length <= 0)
                {
                    textBoxMUACAge.Text = NutriStringConstants.Undefined;
                }

                short gender = 1;

                if (radioButtonFemale.Checked)
                {
                    gender = 2;
                }

                double ZHeight = 50;
                double ZAge = 50;

                ZHeight = AnthStat.NutriDataCalc.GetZScoreHeightMUAC(cm, height, gender);
                ZAge = AnthStat.NutriDataCalc.GetZScoreAgeMUAC(cm, age, gender);

                // Check to make sure the Z-scores aren't ridiculously high or low
                if (ZHeight > 20.0 || ZHeight < -20.0)
                {
                    textBoxMUACHeight.Text = NutriStringConstants.Undefined;
                }
                else
                {
                    textBoxMUACHeight.Text = String.Format(GetPrecisionString(GetPrecisionZ()), ZHeight);
                }

                if (ZAge > 20.0 || ZAge < -20.0)
                {
                    textBoxMUACAge.Text = NutriStringConstants.Undefined;
                }
                else
                {
                    textBoxMUACAge.Text = String.Format(GetPrecisionString(GetPrecisionZ()), ZAge);
                }

            } // end Try

            catch
            {
                MessageBox.Show(SharedStrings.WARNING_INVALID_PARAMETER_MUAC1, 
                    SharedStrings.WARNING, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                textBoxHeadCircumP.Text = NutriStringConstants.Empty;
                textBoxHeadCircumZ.Text = NutriStringConstants.Empty;

            } // end catch         

        } // end CalcMUAC

        /// <summary>
        /// Formats a z-score according to the program's settings XML file.
        /// </summary>
        /// <param name="input">The z-score to be formatted</param>        
        /// <returns>string</returns>
        private string FormatZScore(string input)
        {
            double num;

            try
            {
                num = Convert.ToDouble(input);
                num = Math.Round(num, config.PrecisionZ);
                input = String.Format(GetPrecisionString(config.PrecisionZ), num);
            }
            catch
            {
                return NutriStringConstants.Undefined;
            }
            return input;
        }

        /// <summary>
        /// Formats a percentile according to the program's settings XML file.
        /// </summary>
        /// <param name="input">The percentile to be formatted</param>        
        /// <returns>string</returns>
        private string FormatPercentile(string input)
        {
            try
            {
                double num;
                num = Convert.ToDouble(input);
                num = Math.Round(num, config.PrecisionC);
                if (num < 0 || num > 100)
                {
                    return NutriStringConstants.Undefined;
                }

                if (config.PrecisionC <= 1)
                {
                    if (num >= 99.9)
                        num = 99.9;
                }
                else if (config.PrecisionC == 2)
                {
                    if (num >= 99.99)
                        num = 99.99;
                }

                else if (config.PrecisionC == 3)
                {
                    if (num >= 99.999)
                        num = 99.999;
                }
                else
                {
                    if (num >= 99.9999)
                        num = 99.9999;
                }

                input = String.Format(GetPrecisionString(config.PrecisionC), num);
            }
            catch
            {
                return NutriStringConstants.Undefined;
            }
            return input;
        }
        #endregion Private Methods
        #endregion Methods

        #region Events
        /// <summary>
        /// Handles the TextChanged event for the *legacy* MUAC z-for-age measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxMUACAge_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }

        /// <summary>
        /// Handles the TextChanged event for the *legacy* MUAC z-for-height measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxMUACHeight_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }

        /// <summary>
        /// Handles the TextChanged event of the age (months) text box
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxAgeMonths_TextChanged(object sender, EventArgs e)
        {        
            InputsUpdated = true;
            Patient.Visit.Age = textBoxAgeMonths.Text;

            // Add code to disable 'Recumbent' check box and clear any check mark
            // like Epi 3 does if age > 36 months
            try
            {
                if (textBoxAgeMonths.Text.Length > 0)
                {
                    double ageMonths = 0.0;
                    ageMonths = Convert.ToDouble(textBoxAgeMonths.Text);
                    if (ageMonths > 36.001)
                    {
                        checkBoxRecumbent.Checked = false;
                        checkBoxRecumbent.Enabled = false;
                    }
                    else
                    {
                        checkBoxRecumbent.Enabled = true;
                    }
                }
                else
                {
                    checkBoxRecumbent.Enabled = true;
                }
            }
            catch
            {
                checkBoxRecumbent.Enabled = true;
            }
        }

        /// <summary>
        /// Handles the TextChanged event for the height measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxHeight_TextChanged(object sender, EventArgs e) 
        { 
            InputsUpdated = true;
            if (string.IsNullOrEmpty(textBoxHeight.Text))
            {
                Patient.Visit.HeightCustomary = NutriStringConstants.Empty;
                Patient.Visit.HeightMetric = NutriStringConstants.Empty;
                Patient.Visit.BMI = NutriStringConstants.Empty;
            }
        }

        /// <summary>
        /// Handles the TextChanged event for the age in months measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxAgeYears_TextChanged(object sender, EventArgs e) { /*SetValueChanged(true);*/ }

        /// <summary>
        /// Handles the TextChanged event for the weight measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxWeight_TextChanged(object sender, EventArgs e) 
        { 
            InputsUpdated = true;
            if (string.IsNullOrEmpty(textBoxWeight.Text))
            {
                Patient.Visit.WeightCustomary = NutriStringConstants.Empty;
                Patient.Visit.WeightMetric = NutriStringConstants.Empty;
                Patient.Visit.BMI = NutriStringConstants.Empty;
            }
        }

        /// <summary>
        /// Handles the TextChanged event for the weight in ounces measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxWeightOz_TextChanged(object sender, EventArgs e) { InputsUpdated = true; }

        /// <summary>
        /// Handles the TextChanged event for the head circumference measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxHead_TextChanged(object sender, EventArgs e) 
        { 
            InputsUpdated = true;
            if (string.IsNullOrEmpty(textBoxHead.Text))
            {
                Patient.Visit.HeadCircumferenceCustomary = NutriStringConstants.Empty;
                Patient.Visit.HeadCircumferenceMetric = NutriStringConstants.Empty;
            }
        }

        /// <summary>
        /// Handles the TextChanged event for the mid-upper arm circumference measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxMUAC_TextChanged(object sender, EventArgs e) 
        { 
            InputsUpdated = true;
            if (string.IsNullOrEmpty(textBoxMUAC.Text))
            {
                Patient.Visit.ArmCircumferenceCustomary = NutriStringConstants.Empty;
                Patient.Visit.ArmCircumferenceMetric = NutriStringConstants.Empty;
            }
        }

        /// <summary>
        /// Handles the TextChanged event for the SSF measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxSSF_TextChanged(object sender, EventArgs e) 
        { 
            InputsUpdated = true;
            if (string.IsNullOrEmpty(textBoxSSF.Text))
            {
                Patient.Visit.SubscapularSkinFoldCustomary = NutriStringConstants.Empty;
                Patient.Visit.SubscapularSkinFoldMetric = NutriStringConstants.Empty;
            }
        }

        /// <summary>
        /// Handles the TextChanged event for the TSF measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxTSF_TextChanged(object sender, EventArgs e) 
        { 
            InputsUpdated = true;
            if (string.IsNullOrEmpty(textBoxTSF.Text))
            {
                Patient.Visit.TricepsSkinFoldCustomary = NutriStringConstants.Empty;
                Patient.Visit.TricepsSkinFoldMetric = NutriStringConstants.Empty;
            }
        }

        // start statistic results TextChanged events
        private void textBoxHTforAgeP_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxHTforAgeZ_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxWTforAgeP_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxWTforAgeZ_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxWTforHTP_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxWTforHTZ_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxBMI_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxBMIPercentile_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxBMIZ_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxHeadCircumP_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxHeadCircumZ_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }        
        private void textBoxSSFP_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxSSFZ_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxTSFP_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxTSFZ_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxMUACP_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }
        private void textBoxMUACZ_TextChanged(object sender, EventArgs e) { OutputsUpdated = true; }

        /// <summary>
        /// Handles the KeyDown event of the ID number text box
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxIDNumber_KeyDown(object sender, KeyEventArgs e)
        {
            // Take us directly to the ID number the user entered into the box; in other words, if the user
            // manually enters '134' into the box, take us to patient #134.
            if (e.KeyCode == Keys.Enter)
            {   
                try
                {
                    int id = Convert.ToInt32(textBoxIDNumber.Text);                    
                    AssignDatabaseValues(false, false, id, true, DateTime.Today, false);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }                
            } // end if            
        } // end textBoxIDNumber_KeyDown()

        /// <summary>
        /// Handles the KeyDown event for the date of measurement dateTimePicker field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void dateTimePickerDOM_KeyDown(object sender, KeyEventArgs e)
        {
            // If they press enter, change the age in months field appropriately.
            if (e.KeyCode == Keys.Enter)
                ValidateDates();
        }

        /// <summary>
        /// Handles the KeyPress for the ID number field. Used to load the ID number the user enters.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxIDNumber_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (Char.IsDigit(e.KeyChar) || Char.IsControl(e.KeyChar))
            {
                // Digits and control characters are okay
            }
            else            
                e.Handled = true;
        }

        #region Event Handlers: Leave Events
        // **********************************
        // This block of event handlers makes sure that data is refreshed
        // when the user leaves the field. That each field is of our special
        // NumericTextBox class means input validation is unecessary.
        // **********************************

        private void textBoxAgeMonths_Leave(object sender, EventArgs e)
        {
            if(InputsUpdated)
                RefreshData(1);
        }

        private void textBoxAgeYears_Leave(object sender, EventArgs e)
        {            
            if (textBoxAgeYears.Text.Length > 0)
            {
                double months = -1.0;
                try
                {
                    months = Convert.ToDouble(textBoxAgeYears.Text);                    
                }
                catch
                {
                    months = -1.0;
                }

                months = months * 12.0;

                textBoxAgeMonths.Text = months.ToString();
                textBoxAgeYears.Clear();
                if(InputsUpdated)
                    RefreshData(1);
            }
        }

        private void textBoxHeight_Leave(object sender, EventArgs e)
        {
            if (InputsUpdated)
                RefreshData(4);
        }

        private void textBoxWeight_Leave(object sender, EventArgs e)
        {
            if (InputsUpdated)
                RefreshData(3);
        }

        private void textBoxWeightOz_Leave(object sender, EventArgs e)
        {
            if (InputsUpdated)
                RefreshData(3);
        }

        private void textBoxHead_Leave(object sender, EventArgs e)
        {
            if (InputsUpdated)
                RefreshData(5);
        }

        private void textBoxMUAC_Leave(object sender, EventArgs e)
        {
            if (InputsUpdated)
                RefreshData(6);
        }

        private void textBoxSSF_Leave(object sender, EventArgs e)
        {
            if (InputsUpdated)
                RefreshData(7);
        }

        private void textBoxTSF_Leave(object sender, EventArgs e)
        {
            if (InputsUpdated)
                RefreshData(8);
        }

        /// <summary>
        /// Handles the leave event for the dateTimePickerDOM field. 
        /// Used primarily to validate the date in the date of measurement field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void dateTimePickerDOM_Leave(object sender, EventArgs e)
        {
            ValidateDates();

        } // end dateTimePickerDOM_Leave()
        
        /// <summary>
        /// Handles the leave event for the dateTimePickerDOB field. 
        /// Used primarily to validate the date in the date of birth field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void dateTimePickerDOB_Leave(object sender, EventArgs e)
        {
            // Having a DOB that is after the date of measurement is a problem. We
            // need to check for this!
            if ((dateTimePickerDOM.Value < dateTimePickerDOB.Value) && dateTimePickerDOB.Checked)
            {                
                //MessageBox.Show("Warning: Date of measurement is prior to the date of birth.", "Date conflict", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                ValidateDates();
                
            } // end if

        }

        #endregion Event Handlers: Leave Events

        /// <summary>
        /// Handles the click event for the 'recently opened files' list. 
        /// Only works with MS Access databases.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void MRU_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(sender.ToString());            
            string fullPath = sender.ToString();

            int separator = fullPath.IndexOf("::");
            string fileName = fullPath.Substring(0, separator);
            string tableName = fullPath.Replace(fileName, string.Empty);
            tableName = tableName.Replace("::", string.Empty);
            //MessageBox.Show("File name: [" + fileName + "]   " + "Table name: [" + tableName + "]");
            NutriStat.Data.IDbDriver db;
            DataTable dt;

            try
            {
                db = new AccessDatabase();
                db.ConnectionString = AccessDatabase.BuildConnectionString(fileName, null);

                dt = db.GetTableData(tableName, "*", "fldIdNo, fldCurrentDate ASC");
                dt.TableName = tableName;

                Patient.Database = db;
                Patient.Table = dt;
                db.Dispose();
                dt.Dispose();
                OpenDatabase();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        
        /// <summary>
        /// Handles the click event for the Grid button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonGrid_Click(object sender, EventArgs e)
        {            
            ShowGrid();         
        }

        /// <summary>
        /// Handles the click event for the Search button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonSearch_Click(object sender, EventArgs e)
        {
            if (!DatabaseLoaded)
                return;
            /*  
            FormExportCustom findRecords = new FormExportCustom(this, true);
            findRecords.Show();
            */
        }
        
        /// <summary>
        /// Handles the Click event for the Delete button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonDelete_Click(object sender, EventArgs e)
        {
            if (!DatabaseLoaded)
                return;

            // Notes:   This is called when the user clicks the 'delete' button.
            //          This does not delete the entire record set for that ID number, it just
            //          deletes the current date of measurement. 

            string id = textBoxIDNumber.Text;
            string DOM = dateTimePickerDOM.Text;

            // Show a dialog that explains exactly what is happening. The user can't undo this action.
            DialogResult result = MessageBox.Show(/*"This will delete measurement date " + DOM + " from ID number " + id + ". Are " +
                "you sure you wish to continue? This action cannot be undone."*/ string.Format(
                    SharedStrings.NOTICE_DELETE_RECORD, DOM, id),
                    SharedStrings.NOTICE_DELETE_RECORD_TITLE, MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            // If we get a 'No' then quit
            if (result == DialogResult.No)
            {
                return;
            }
            else
            {
                //Patient.DeleteRecord();
            }
            PopulateFormControls();
            UpdateGridView();
        }

        /// <summary>
        /// Handles the Click event of the 'New date of measurement' button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonDOMNew_Click(object sender, EventArgs e)
        {
            // TODO: Move this to a separate function since it's repeated several times in this code. (Knudsen)
            if (InputsUpdated || OutputsUpdated)
            {
                DialogResult result = MessageBox.Show(SharedStrings.NOTICE_RECORD_MODIFIED,
                    SharedStrings.NOTICE_RECORD_MODIFIED_TITLE, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                // If we get an acknowledgement on our message box, then run SaveData()
                if (result == DialogResult.Yes)
                {
                    SaveData();
                }
                else if (result == DialogResult.Cancel)
                {
                    // If they click cancel, nothing should happen; the record is not saved
                    // and they do not go forward or backwards.
                    return;
                }
            }
            AddNewMeasurement();
        }

        /// <summary>
        /// Handles the Click event of the 'New ID number' button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonNew_Click(object sender, EventArgs e)
        {
            // TODO: Move this to a separate function since it's repeated several times in this code. (Knudsen)
            if (InputsUpdated || OutputsUpdated)
            {
                DialogResult result = MessageBox.Show(SharedStrings.NOTICE_RECORD_MODIFIED,
                    SharedStrings.NOTICE_RECORD_MODIFIED_TITLE, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                // If we get an acknowledgement on our message box, then run SaveData()
                if (result == DialogResult.Yes)
                {
                    SaveData();
                }
                else if (result == DialogResult.Cancel)
                {
                    // If they click cancel, nothing should happen; the record is not saved
                    // and they do not go forward or backwards.
                    return;
                }
            }
            AddNewID();            
        }

        /// <summary>
        /// Handles the click event for the the 'right' button in the date of measurement group box
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonDOMRight_Click(object sender, EventArgs e) 
        { 
            AssignDatabaseValues(true, false, -1, false, dateTimePickerDOM.Value, false); 
        }

        private void buttonDOMLeft_Click(object sender, EventArgs e) { AssignDatabaseValues(false, false, -1, false, dateTimePickerDOM.Value, false); }
        private void buttonRight_Click(object sender, EventArgs e) { AssignDatabaseValues(true, true, -1, false, DateTime.Today, false); }
        private void buttonLeft_Click(object sender, EventArgs e) { AssignDatabaseValues(false, true, -1, false, DateTime.Today, false); }

        /// <summary>
        /// Handles the Click event for the 'go to first record' button.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonLeftFirst_Click(object sender, EventArgs e)
        {
            Patient.LoadFirstRecord();       
            PopulateFormControls();
        }

        /// <summary>
        /// Handles the Click event for the 'go to last record' button.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonRightLast_Click(object sender, EventArgs e)
        {
            Patient.LoadLastRecord();                       
            PopulateFormControls();
        }

        /// <summary>
        /// Handles the FormClosed event for the the main menu form.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void FormMainMenu_FormClosed(object sender, FormClosedEventArgs e)
        {
        }

        /// <summary>
        /// Handles the Load event for the the main menu form.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void FormMainMenu_Load(object sender, EventArgs e)
        {
            config = new NutriConfig();
            NutriConfig.SetCurrentDirectory(Directory.GetCurrentDirectory());
            ConfigureFormControls();
            CheckResultsForNullValues();
        }

        /// <summary>
        /// Handles the FormClosing event for the the main menu form.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void FormMainMenu_FormClosing(object sender, FormClosingEventArgs e)
        { 
            // Prompt the user to save any changes prior to closing the form.
            // If they select cancel, however, we want to cancel the close
            // operation too, so we need to check for this.
            bool close = ShowSaveDataPrompt();
            if (!close)
                e.Cancel = true;
        }
        
        /// <summary>
        /// Handles the Click event for the 'New Table' menu item in the file menu.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void newTableToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NewTableDialog newTableDialog;

            if (!DatabaseLoaded)
                newTableDialog = new NewTableDialog(this);
            else
                newTableDialog = new NewTableDialog(this, Patient.Database, Patient.Table);

            newTableDialog.Show(this);            
        }
        
        /// <summary>
        /// Handles the Click event for the 'Open Table' menu item in the file menu.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void openTableToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenTableDialog openTableDialog;

            if(!DatabaseLoaded)
                openTableDialog = new OpenTableDialog(this);
            else
                openTableDialog = new OpenTableDialog(this, Patient.Database, Patient.Table);

            openTableDialog.Show(this);
        }

        /// <summary>
        /// Handles the Click event for the 'Import' menu item in the file > external data menu.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void importToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ImportTableDialog importTableDialog;
            
            if(!DatabaseLoaded)
                importTableDialog = new ImportTableDialog(this);
            else
                importTableDialog = new ImportTableDialog(this);

            importTableDialog.Show(this);             
            
        }
        
        /// <summary>
        /// Handles the Click event for the 'Save Record' menu item in the navigation menu.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void saveRecordToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveData();
            InputsUpdated = false;
            PatientInfoChanged = false;
            OutputsUpdated = false;
            LoadingRecord = false;
        }

        /// <summary>
        /// Handles the Click event for the 'Export all records' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void allRecordsToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the Click event for the 'Export all records for this ID' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void allRecordsForCurrentIDToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the Click event for the 'Export curent record' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void currentRecordToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the Click event for the 'Custom Export' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void customToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the Click event for the 'Exit' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {            
            this.Close();
        }

        /// <summary>
        /// Handles the Click event for the 'Cut' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Get the currently-active form control
            Control control = this.ActiveControl;

            // Is it null? If so, don't do anything.
            if (control != null)
            {
                // Determine what kind of control it is
                if (control is TextBox)
                {                    
                    TextBox textBox = (TextBox)control;
                    textBox.Cut();
                }
                else if (control is NumericTextBox)
                {
                    NumericTextBox numericTextBox = (NumericTextBox)control;
                    numericTextBox.Cut();
                }
            }
        }

        /// <summary>
        /// Handles the Click event for the 'Copy' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Control control = this.ActiveControl;

            if (control != null)
            {
                if (control is TextBox)
                {
                    TextBox textBox = (TextBox)control;
                    textBox.Copy();
                }
                else if (control is NumericTextBox)
                {
                    NumericTextBox numericTextBox = (NumericTextBox)control;
                    numericTextBox.Copy();
                }
            }
        }

        /// <summary>
        /// Handles the Click event for the 'Paste' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {            
            Control control = this.ActiveControl;

            if (control != null)
            {
                if (control is TextBox)
                {
                    TextBox textBox = (TextBox)control;
                    textBox.Paste();
                }
                else if (control is NumericTextBox)
                {
                    NumericTextBox numericTextBox = (NumericTextBox)control;
                    numericTextBox.Paste();
                }
            }
        }

        /// <summary>
        /// Handles the Click event for the 'Find' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void findToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!DatabaseLoaded)
            {
                return;
            }

            FindRecordsDialogBase findRecords = new FindRecordsDialogBase(this, true, config);
            findRecords.Show();            
        }

        /// <summary>
        /// Handles the Click event for the 'Grid' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void gridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ShowGrid();
        }

        /// <summary>
        /// Handles the Click event for the 'Refresh' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!DatabaseLoaded)
            {
                return;
            }

            try
            {
                string id = textBoxIDNumber.Text;
                DateTime DOM = dateTimePickerDOM.Value;                
                PopulateFormControls();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// Handles the Click event for the 'Options' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OptionsDialog options = new OptionsDialog(this, config);
            options.Show();
        }

        /// <summary>
        /// Handles the Click event for the 'About' toolstrip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox aboutBox = new AboutBox();
            aboutBox.Show();
        }

        /// <summary>
        /// Handles the Click event for the Graph button.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void buttonGraph_Click(object sender, EventArgs e)
        {
            DisplayGraphOptions();                        
        }
        
        /// <summary>
        /// Handles the CheckChanged event for the Recumbent check box.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void checkBoxRecumbent_CheckedChanged(object sender, EventArgs e)
        {         
            InputsUpdated = true;

            // update the patient object
            Patient.Visit.Recumbent = checkBoxRecumbent.Checked;
            if (checkBoxRecumbent.Checked)
            {
                labelHeight.Text = SharedStrings.LENGTH;               // change the height label to say "length"
                labelWTforHT.Text = SharedStrings.WEIGHT_FOR_LENGTH;    // update the weight-for-height label
                labelHTforAge.Text = SharedStrings.LENGTH_FOR_AGE;      // update the height-for-age label
                Patient.Visit.Recumbent = true;
            }
            else
            {
                labelHeight.Text = SharedStrings.HEIGHT;               // change the height label to say "height"
                labelWTforHT.Text = SharedStrings.WEIGHT_FOR_HEIGHT;    // update the weight-for-height label
                labelHTforAge.Text = SharedStrings.HEIGHT_FOR_AGE;      // update the height-for-age label
                Patient.Visit.Recumbent = false;
            }
            if (!LoadingRecord)            
                RefreshData(0);
            
        } // end checkBoxRecumbent_CheckedChanged()        

        /// <summary>
        /// Handles the ValueChanged event for the Date of Measurement dateTimePicker field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void dateTimePickerDOM_ValueChanged(object sender, EventArgs e)
        {            
            Patient.Visit.VisitDate = dateTimePickerDOM.Value;
            InputsUpdated = true;
            ValidateDates();            
        }

        /// <summary>
        /// Handles the CheckedChanged event for the 'Male' radio button.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void radioButtonMale_CheckedChanged(object sender, EventArgs e)
        {
            if (!LoadingRecord)
            {
                RefreshData(0);
            }

            if (radioButtonMale.Checked)
            {
                Patient.Gender = "M";
            }
            else
            {
                Patient.Gender = "F";
            }

            PatientInfoChanged = true;
            InputsUpdated = true;
        }

        /// <summary>
        /// Handles the CheckedChanged event for the 'Female' radio button.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void radioButtonFemale_CheckedChanged(object sender, EventArgs e)
        {
            if (!LoadingRecord)
            {
                RefreshData(0);
            }

            if (radioButtonFemale.Checked)
            {
                Patient.Gender = "F";
            }
            else
            {
                Patient.Gender = "M";
            }

            PatientInfoChanged = true;
            InputsUpdated = true;
        }

        /// <summary>
        /// Handles the ValueChanged event for the Date of Birth dateTimePicker field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void dateTimePickerDOB_ValueChanged(object sender, EventArgs e)
        {
            if (!LoadingRecord)
            {
                RefreshData(0);
            }
            
            InputsUpdated = true;
            PatientInfoChanged = true;
            Patient.BirthDate = dateTimePickerDOB.Value;
            
            if (dateTimePickerDOB.Checked == true)
            {
                textBoxAgeMonths.ReadOnly = true;
                textBoxAgeYears.ReadOnly = true;
            }
            else
            {
                textBoxAgeMonths.ReadOnly = false;
                textBoxAgeYears.ReadOnly = false;
            }
        }

        /// <summary>
        /// Handles the MouseDown event for the Date of Birth dateTimePicker field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void dateTimePickerDOB_MouseDown(object sender, MouseEventArgs e)
        {
            // We have to do some hacks to get certain functionality working right 
            // and this event is key... basically, unchecking the DOM date control
            // does not always turn off read only mode on the textBoxFields, probably
            // because we do that in the ValueChanged field. Now ideally this would
            // be done in a checkChanged event except this control does not HAVE
            // a checkChanged event. (TODO: Add one?) So we instead use the MouseDown
            // event to check for it but this requires some additional work,             
            
            if (dateTimePickerDOB.Checked == true)
            {
                textBoxAgeMonths.ReadOnly = true;
                textBoxAgeYears.ReadOnly = true;
            }
            else
            {
                textBoxAgeMonths.ReadOnly = false;
                textBoxAgeYears.ReadOnly = false;
            }
        }

        /// <summary>
        /// Handles the TextChanged event for the last name field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxLastName_TextChanged(object sender, EventArgs e)
        {            
            PatientInfoChanged = true;
            InputsUpdated = true;
            Patient.LastName = textBoxLastName.Text;
        }

        /// <summary>
        /// Handles the TextChanged event for the first name field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void textBoxFirstName_TextChanged(object sender, EventArgs e)
        {
            PatientInfoChanged = true;
            InputsUpdated = true;
            Patient.FirstName = textBoxFirstName.Text;
        }

        /// <summary>
        /// Handles the double click event for the grid view.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void dataGridViewMain_RowHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            GridRowClicked();    
        }

        /// <summary>
        /// Handes the click event for the graphing tool strip menu item.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void graphToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DisplayGraphOptions();
        }        

        /// <summary>
        /// Handes when a cell inside of the grid has been clicked
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void dataGridViewMain_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            GridRowClicked();
        }

        /// <summary>
        /// Handes the click event for the HA graph button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void pictureBoxGraphHA_Click(object sender, EventArgs e)
        {            
            DisplayGraph(MeasurementOptions.HA.Abbreviation);
        }

        /// <summary>
        /// Handes the click event for the WA graph button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void pictureBoxGraphWA_Click(object sender, EventArgs e)
        {
            DisplayGraph(MeasurementOptions.WA.Abbreviation);
        }

        /// <summary>
        /// Handes the click event for the WH graph button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void pictureBoxGraphWH_Click(object sender, EventArgs e)
        {
            DisplayGraph(MeasurementOptions.WH.Abbreviation);
        }

        /// <summary>
        /// Handes the click event for the BMI graph button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void pictureBoxGraphBMI_Click(object sender, EventArgs e)
        {
            DisplayGraph(MeasurementOptions.BMI.Abbreviation);
        }

        /// <summary>
        /// Handes the click event for the HCA graph button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void pictureBoxGraphHCA_Click(object sender, EventArgs e)
        {
            DisplayGraph(MeasurementOptions.HCA.Abbreviation);
        }

        /// <summary>
        /// Handes the click event for the arm circumference graph button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void pictureBoxGraphMUACA_Click(object sender, EventArgs e)
        {
            DisplayGraph(MeasurementOptions.MUACA.Abbreviation);
        }

        #endregion Events

        /// <summary>
        /// Handles the TextChanged event for the cluster field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void integerTextBoxCluster_TextChanged(object sender, EventArgs e)
        {           
            PatientInfoChanged = true;
            InputsUpdated = true;
            Patient.Cluster = integerTextBoxCluster.Text;            
        }

        /// <summary>
        /// Handles the TextChanged event for the team field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void integerTextBoxTeam_TextChanged(object sender, EventArgs e)
        {
            PatientInfoChanged = true;
            InputsUpdated = true;
            Patient.Team = integerTextBoxTeam.Text;
        }

        /// <summary>
        /// Handles the TextChanged event for the household field.
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void integerTextBoxHousehold_TextChanged(object sender, EventArgs e)
        {
            PatientInfoChanged = true;
            InputsUpdated = true;
            Patient.Team = integerTextBoxHousehold.Text;
        }


    } // end class

} // end namespace